Как я могу отобразить содержимое карты на консоли?

У меня есть map, объявленный следующим образом:

map < string , list < string > > mapex ; list< string > li;

Как я могу отобразить элементы, хранящиеся на приведенной выше карте, на консоли?


person Cute    schedule 30.06.2009    source источник


Ответы (7)


Ну, это зависит от того, как вы хотите их отобразить, но вы всегда можете легко повторить их:

typedef map<string, list<string>>::const_iterator MapIterator;
for (MapIterator iter = mapex.begin(); iter != mapex.end(); iter++)
{
    cout << "Key: " << iter->first << endl << "Values:" << endl;
    typedef list<string>::const_iterator ListIterator;
    for (ListIterator list_iter = iter->second.begin(); list_iter != iter->second.end(); list_iter++)
        cout << " " << *list_iter << endl;
}
person Skurmedel    schedule 30.06.2009
comment
@triclosan: Вы также можете предварительно увеличить, в данном случае это не имеет значения. Или я вас неправильно понял? - person Skurmedel; 15.11.2013
comment
использование постинкрементного усиления для создания дополнительных временных объектов - person triclosan; 16.11.2013
comment
@triclosan: Возможно, или компилятор оптимизирует его для вас. Невозможно сказать, не попробовав. И по большому счету мы используем стандартный вывод консоли iostream, который с точки зрения производительности затмевает любые затраты на дополнительный объект итератора объекта. - person Skurmedel; 16.11.2013

Обновление (назад в будущее): с циклами for на основе диапазона C++ 11 —

std::map<Key, Value> m { ... /* initialize it */ ... };

for (const auto &p : m) {
    std::cout << "m[" << p.first << "] = " << p.second << '\n';
}
person The Paramagnetic Croissant    schedule 03.12.2014

я бы попробовал следующее

void dump_list(const std::list<string>& l) {
  for ( std::list<string>::const_iterator it = l.begin(); l != l.end(); l++ ) {
    cout << *l << endl;
  }
}

void dump_map(const std::map<string, std::list<string>>& map) {
  for ( std::map<string,std::list<string>>::const_iterator it = map.begin(); it != map.end(); it++) {
    cout << "Key: " << it->first << endl;
    cout << "Values" << endl;
    dump_list(it->second);
}
person JaredPar    schedule 30.06.2009
comment
Получил expected unqualified-id before '<' token в первой строке: void dump_list(const std::list<string>& l) {. Должен ли я что-то включать? - person The Student; 15.01.2013
comment
В dump_list должно быть так: std::vector‹type›::const_iterator it = l.begin(); for ( it; it != l.end(); ++ it ) { std::cout ‹‹ *it ‹‹ std::endl; } и не л в cout! В остальном это было очень полезно для меня / Спасибо! - person Kahin; 29.01.2015

Я тут немного не в тему...

Я думаю, вы хотите сбросить содержимое карты для отладки. Я хотел бы упомянуть, что следующий выпуск gdb (версия 7.0) будет иметь встроенный интерпретатор Python, который будет использоваться gcc libstdc++ для предоставления красивых принтеров stl. Вот пример для вашего случая

  #include <map>
  #include <map>
  #include <list>
  #include <string>

  using namespace std;

  int main()
  {
    typedef map<string, list<string> > map_type;
    map_type mymap;

    list<string> mylist;
    mylist.push_back("item 1");
    mylist.push_back("item 2");
    mymap["foo"] =  mylist;
    mymap["bar"] =  mylist;

    return 0; // stopped here
  }

что приводит к

(gdb) print mymap
$1 = std::map with 2 elements = {
  ["bar"] = std::list = {
    [0] = "item 1",
    [1] = "item 2"
  },
  ["foo"] = std::list = {
    [0] = "item 1",
    [1] = "item 2"
  }
}

Ура!

person Maik Beckmann    schedule 30.06.2009

Другая форма с использованием <algorithm>:

void printPair(const pair<string, list<string> > &p)
{
    cout << "Key: " << p.first << endl;
    copy(p.second.begin(), p.second.end(), ostream_iterator<string>(cout, "\n"));
}    
for_each(mapex.begin(), mapex.end(), printPair);

Программа испытаний:

#include <iostream>
#include <map>
#include <list>
#include <iterator>
#include <algorithm>
using namespace std;

void printPair(const pair<string, list<string> > &p)
{
    cout << "Key: " << p.first << endl;
    copy(p.second.begin(), p.second.end(), ostream_iterator<string>(cout, "\n"));
}

int main()
{
    map<string, list<string> >  mapex;

    list<string> mylist1;
    mylist1.push_back("item 1");
    mylist1.push_back("item 2");
    mapex["foo"] =  mylist1;
    list<string> mylist2;
    mylist2.push_back("item 3");
    mylist2.push_back("item 4");
    mylist2.push_back("item 5");
    mapex["bar"] =  mylist2;

    for_each(mapex.begin(), mapex.end(), printPair);
}
person mMontu    schedule 22.11.2013

Вы можете написать довольно общую перегруженную функцию, которая хороша для двух целей:

  1. Работает с любым map.
  2. Это позволяет использовать <<.

Функция

template<class key_t, class value_t>
ostream& operator<<(ostream& os, const map<key_t, value_t>& m) {
    for (typename map<key_t, value_t>::const_iterator it = m.begin();
            it != m.end(); it++) {
        os << "Key: " << it->first << ", Value: " << it->second;
    }
    return os;
}

cout << будет работать с любым map, для которого << определено для typenames key_t и value_t. В вашем случае это не определено для value_t (= list<string>), поэтому вы также должны его определить. В том же духе вы можете использовать

template<class T>
ostream& operator<<(ostream& os, const list<T>& l) {
    for (typename list<T>::const_iterator it = l.begin(); it != l.end(); it++) {
        os << "\"" << *it << "\", ";
    }
    return os;
}

Итак, вы можете:

  1. Добавьте эти две функции.
  2. Добавьте прототипы там, где это необходимо.
  3. Используйте using namespace std; (или добавьте std:: по мере необходимости).
  4. Используйте, например,
    cout << mapex << endl;
    cout << li << endl;

Помните, что если есть какой-либо другой жизнеспособный кандидат для только что определенных << (которого, как я понимаю, нет, иначе вы, вероятно, не задали бы этот вопрос), он может иметь приоритет над текущими.

person sancho.s ReinstateMonicaCellio    schedule 12.10.2016

Если вы можете использовать функции C++11, то я думаю, что циклы for на основе диапазона, как предложено в Ответ Парамагнитного Круассана обеспечивает наиболее читаемый вариант. Однако если вам доступен C++17, вы можете комбинировать эти циклы с структурированными привязками для дальнейшего повышения удобочитаемости, поскольку вам больше не нужно используйте элементы first и second. Для вашего конкретного случая использования мое решение будет выглядеть следующим образом:

std::map<std::string, std::list<std::string>> mapex;
mapex["a"] = { "1", "2", "3", "4" };
mapex["b"] = { "5", "6", "7" };

for (const auto &[k, v] : mapex) {
    std::cout << "m[" << k.c_str() << "] =";
    for (const auto &s : v)
        std::cout << " " << s.c_str();
    std::cout << std::endl;
}

Выход:

m[a] = 1 2 3 4
m[b] = 5 6 7

Код на Coliru

person honk    schedule 21.03.2019