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

前端 未结 7 1455
轻奢々
轻奢々 2020-12-28 13:41

I have a map declared as follows:

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

How can I disp

相关标签:
7条回答
  • 2020-12-28 13:47

    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!

    0 讨论(0)
  • 2020-12-28 13:48

    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;
    }
    
    0 讨论(0)
  • 2020-12-28 13:53

    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';
    }
    
    0 讨论(0)
  • 2020-12-28 13:54

    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);
    }
    
    0 讨论(0)
  • 2020-12-28 13:56

    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

    0 讨论(0)
  • 2020-12-28 13:58

    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.

    0 讨论(0)
提交回复
热议问题