How can I display the content of a map on the console?

限于喜欢 提交于 2019-12-30 00:15:36

问题


I have a map declared as follows:

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

How can I display the items stored in the above map on the console?


回答1:


Well it depends on how you want to display them, but you can always iterate them easily:

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;
}



回答2:


Update (Back to the future): with C++11 range-based for loops –

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

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



回答3:


I'd try the following

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);
}



回答4:


I'm a little off topic here...

I guess you want to dump the map content for debugging. I like to mention that the next gdb release (version 7.0) will have a built in python interpreter which will be used by the gcc libstdc++ to provide stl pretty printers. Here is an example for your case

  #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
  }

which results in

(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"
  }
}

Yay!




回答5:


Another form, using <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);

Test program:

#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);
}



回答6:


You can write a quite generic overloaded function, which is good for two purposes:

  1. It works with any map.
  2. It allows for using <<.

The function is

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 << will work with any map for which << is defined for typenames key_t and value_t. In your case, this is not defined for value_t (= list<string>), so you also have to define it. In a similar spirit, you can use

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;
}

So, you may:

  1. Add these two functions.
  2. Add the prototypes where needed.
  3. Use using namespace std; (or add std:: as needed).
  4. Use, e.g.,
    cout << mapex << endl;
    cout << li << endl;

Remember that if there is any other viable candidate for the <<s just defined (which I take there is not, otherwise you would likely not ask this question), it may take precedence over the present ones.




回答7:


If you can use C++11 features, then I think range-based for loops as proposed in The Paramagnetic Croissant's answer provide the most readable option. However, if C++17 is available to you, then you can combine those loops with structured bindings to further increase readability, because you no longer need to use the first and second members. For your specific use case, my solution would look as follows:

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;
}

Output:

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

Code on Coliru



来源:https://stackoverflow.com/questions/1063453/how-can-i-display-the-content-of-a-map-on-the-console

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!