web-dev-qa-db-fra.com

Comment afficher le contenu d'une carte sur la console?

J'ai un map déclaré comme suit:

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

Comment puis-je afficher les éléments stockés dans la carte ci-dessus sur la console?

31
Cute

Cela dépend de la façon dont vous souhaitez les afficher, mais vous pouvez toujours les répéter facilement:

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

Mise à jour (Retour vers le futur): avec la gamme C++ 11 basée sur les boucles -

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

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

J'essaierais ce qui suit

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

Je suis un peu hors sujet ici ...

Je suppose que vous voulez vider le contenu de la carte pour le débogage. J'aime mentionner que la prochaine version de gdb (version 7.0) aura un interpréteur python intégré qui sera utilisé par gcc libstdc ++ pour fournir de jolies imprimantes stl. Voici un exemple pour votre cas

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

ce qui se traduit par

(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
Maik Beckmann

Un autre formulaire, utilisant <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);

Programme de test:

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

Vous pouvez écrire une fonction surchargée assez générique, ce qui est bon à deux fins:

  1. Il fonctionne avec n'importe quel map.
  2. Il permet d'utiliser <<.

La fonction est

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 << fonctionnera avec tout map pour lequel << est défini pour typenames key_t et value_t. Dans votre cas, cela n'est pas défini pour value_t (= list<string>), vous devez donc également le définir. Dans un esprit similaire, vous pouvez utiliser

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

Vous pouvez donc:

  1. Ajoutez ces deux fonctions.
  2. Ajoutez les prototypes si nécessaire.
  3. Utilisation using namespace std; (ou ajoutez std:: comme requis).
  4. Utilisez, par exemple,
    cout << mapex << endl;
    cout << li << endl;

N'oubliez pas que s'il existe un autre candidat viable pour le <<s juste défini (ce que je prends pas, sinon vous ne poseriez probablement pas cette question), il peut avoir la priorité sur les présentes.

1
sancho.s

Si vous pouvez utiliser C++ 11 les fonctionnalités, alors je pense que basé sur la plage pour les boucles comme proposé dans La réponse du croissant paramagnétique fournit le plus lisible option. Cependant, si C++ 17 est à votre disposition, vous pouvez combiner ces boucles avec liaisons structurées pour augmenter encore la lisibilité, car vous n'avez plus besoin d'utiliser le first et second. Pour votre cas d'utilisation spécifique, ma solution se présenterait comme suit:

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

Production:

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

Code sur Colir

0
honk