IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SL & STL C++ Discussion :

Problème avec map


Sujet :

SL & STL C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Novembre 2002
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 55
    Par défaut Problème avec map
    Bonjour


    Au code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
     
    std::map<char ,int> bonjour; bonjour["titi"] = 2;


    j'ai à la compil le résultat suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    c:\program files\microsoft visual studio\vc98\include\xtree(200) : warning C4786: '?rbegin@?$_Tree@VCString@@U?$pair@$$CBVCString@@H@std@@U_Kfn@?$map@VCString@@HU?$less@VCString@@@std@@V?$allocator@H@3@@3@U?$less@VCString@@@3@V?$allocator@H@3@@std@@
    QAE?AV?$reverse_bidirectional_iterator@Viterator@?$_Tree@VCString@@U?$pair@$$CBVCString@@H@std@@U_Kfn@?$map@VCString@@HU?$less@VCString@@@std@@V?$allocator@H@3@@3@U?$less@VCString@@@3@V?$allocator@H@3@@std@@U?$pair@$$CBVCString@@H@3@AAU43@PAU43@H@2@
    XZ' : identifier was truncated to '255' characters in the browser information
            c:\program files\microsoft visual studio\vc98\include\map(46) : see reference to class template instantiation 'std::_Tree<class CString,struct std::pair<class CString const ,int>,struct std::map<class CString,int,struct std::less<class CStri
    ng>,class std::allocator<int> >::_Kfn,struct std::less<class CString>,class std::allocator<int> >' being compiled
            E:\Projets\DemoCityRama\Services.cpp(21) : see reference to class template instantiation 'std::map<class CString,int,struct std::less<class CString>,class std::allocator<int> >' being compiled
    c:\program files\microsoft visual studio\vc98\include\xtree(202) : warning C4786: 
     
    ....
    QQu'un aurait il une idée?
    Merci

  2. #2
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    Oula le message de VC fait peur, pas très logique tout ça.
    L'erreur c'est que tu tentes de convertir un const char* en char... forcément ça péte.

  3. #3
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Tu prends déjà un bon départ en tentant d'utiliser la STL pour ta collection...

    Pourquoi n'irais tu pas "un peu plus loin" en utilisant... la classe std::string pour représenter ta chaine de caractères

    En effet, il y a le problème que tu déclare la clé comme étant un... char, c'est à dire un... caractère unique.

    Or, si je compte bien, "titi" est composé de... 4 caractères significatifs (5 si on compte le '\0' terminal), et ca, ca s'appelle un tableau de caractères, et, dans le meilleur des cas, on le déclare sous la forme... d'un pointeur de type char

    Mais le fait de déclarer ta map sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::map<char *, int> bonjour;
    ne suffirait, malheureusement, pas à résoudre ton problème...

    En effet, un tableau de caractères dont le dernier caractère significatif est suivi par un '\0' représente... une chaine de caractère dite "C style", mais il n'en demeure pas moins qu'un char *, c'est un pointeur, et qu'un pointeur, ce n'est jamais... qu'une variable numérique non signée représentant... l'adresse à laquelle on trouvera l' "objet" dont le type est donné (ici, l'objet est... un caractère).

    Or, c'est la valeur de l'adresse qui serait comparée si tu utilisait un char * comme clé pour ta map et ca, ca risquerait de provoquer une situation assez embêtante:

    Il n'est pas du tout exclu que deux chaines de caractères identiques ( "titi", par exemple) se trouvent... en deux adresses mémoire différentes ce qui fait qu'elles seraient considérées comme... différentes, alors qu'elle devraient... être considérées comme équivalentes

    C'est pour cette raison qu'en C, lorsqu'il est question de comparer deux chaines de caractères, il faut avoir recours à ... la fonction strcmp.

    Et nous avons un autre problème propre à l'utilisation de la map: Il n'est pas possible de demander à la map d'utiliser directement la fonction strcmp comme comparateur, car le système permettant de trier les tris est basé sur l'opérateur < (ou sur le prédicat less).

    Et comme si, effectivement, l'opérateur < fonctionne pour un pointeur, c'est l'adresse qu'il contient qui est comparée, c'est à dire que, avec un peu de mal chance, la chaine de caractère "zozo" se trouvera à une adresse inférieure que la chaine de caractère "titi", et que, du coup, la map considérera que "zozo" est... plus petit que titi...

    Du coups, les éléments ont de grandes chances de ne pas être correctement triés dans la std::map...

    Il faut avouer que c'est réellement dommage, non

    Et je ne te ferai pas l'affront de te rappeler tous les autres problèmes liés à l'utilisation des chaines de caractères C style du point de vue de la gestion dynamique de la mémoire

    C'est donc dans ce contexte que la classe std::string intervient.

    D'abord, il faut savoir que cette classe dispose de de l'opérateur < qui permet, effectivement, de savoir si une chaine est plus petite ou plus grande qu'une autre. (d'ailleurs, elle dispose également de l'opérateur de comparaison == et des opérateurs + et += qui servent dans un contexte de concaténation )

    De plus, cette classe gère automatiquement l'espace mémoire dont elle a besoin, ce qui nous permet de ne plus nous en inquiéter

    Enfin, elle est pleinement compatible avec des char const * dans le sens où elle dispose d'un constructeur prenant un tel pointeur en argument ainsi que d'une fonction c_str() permettant, en cas de besoin, de récupérer un char const *.

    Et je ne te parle pas des autres fonctions membres dont elle est affublée, parce que la liste est vraiment longue, mais sache qu'elle permet énormément de choses

    Bref, tu l'auras surement compris en me lisant: il est vraiment préférable d'utiliser la classe std::string chaque fois qu'il te faut gérer des chaines de caractères plutôt que d'utiliser les chaines de caractères C style

    Au final, tous tes problèmes trouveraient une solution, et tu t'en éviterais sans doute beaucoup d'autres en déclarant ta std::map sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::map<std::string, int> bonjour;
    Cependant, je ne peux me résoudre à terminer cette (déjà longue) intervention sans te prodiguer un dernier conseil:

    La comparaison de chaines de caractères prend *énormément* de temps par rapport à la comparaison de valeurs numériques.

    En effet, elle nécessite de comparer un à un les différents caractères de la "première" chaine de caractères avec... le caractère occupant la position correspondante de la "deuxième" chaine de caractères.

    Sur de "petites" chaines de caractères, et, au vu de la puissances des ordianteurs actuels, il est possible que cela n'impacte pas *trop* sur les performances, mais, si les chaines de caractères deviennent importantes et qu'il y en a beaucoup à comparer, l'utilisation d'une chaine de caractères comme clé de tri est *réellement* de nature à "plomber" les performances de la std::map.

    Si les performances sont importantes pour ton projet, il est *peut-être* intéressant d'envisager l'utilisation d'une autre sorte de clé de tri .
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  4. #4
    Membre confirmé
    Inscrit en
    Novembre 2002
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 55
    Par défaut
    Déjà merci pour ces explications très intéressantes...

    Mais tjrs le meme pb, à la compile de ce code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    	std::map <std::string, int> bonjour;
    	bonjour["cou"] = 2;
    j'obtiens les warnings suivantes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    c:\program files\microsoft visual studio\vc98\include\map(27) : warning C4786: '??R_Kfn@?$map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@HU?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@H@2@@s
    td@@QBEABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@ABU?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@2@@Z' : identifier was truncated to '255' characters in the browser information
            E:\Projets\DemoCityRama\Services.cpp(25) : see reference to class template instantiation 'std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int,struct std::less<class std::basic_string<char,stru
    ct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<int> >' being compiled
    c:\program files\microsoft visual studio\vc98\include\map(36) : warning C4786: '??Rvalue_compare@?$map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@HU?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocat
    or@H@2@@std@@QBE_NABU?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@2@0@Z' : identifier was truncated to '255' characters in the browser information
            E:\Projets\DemoCityRama\Services.cpp(25) : see reference to class template instantiation 'std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int,struct std::less<class std::basic_string<char,stru
    ct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<int> >' being compiled
    c:\program files\microsoft visual studio\vc98\include\map(38) : warning C4786: '??0value_compare@?$map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@HU?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocat
    or@H@2@@std@@QAE@U?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@Z' : identifier was truncated to '255' characters in the browser information
            E:\Projets\DemoCityRama\Services.cpp(25) : see reference to class template instantiation 'std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int,struct std::less<class std::basic_string<char,stru
    ct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<int> >' being compiled
    c:\program files\microsoft visual studio\vc98\include\map(45) : warning C4786: '?$_Tree@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@2@U_Kfn@?$map@V?$basic_
    string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@HU?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@H@2@@2@U?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@H@2@' : identifi
    er was truncated to '255' characters in the browser information
            E:\Projets\DemoCityRama\Services.cpp(25) : see reference to class template instantiation 'std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int,struct std::less<class std::basic_string<char,stru
    ct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<int> >' being compiled
    c:\program files\microsoft visual studio\vc98\include\xtree(22) : warning C4786: '?$_Tree@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@2@U_Kfn@?$map@V?$basi
    c_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@HU?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@H@2@@2@U?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@H@2@' : identi
    fier was truncated to '255' characters in the browser information
    ....
    avec les erreurs suivantes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    c:\program files\microsoft visual studio\vc98\include\functional(86) : error C2784: 'bool __cdecl std::operator <(const class std::multimap<_K,_Ty,_Pr,_A> &,const class std::multimap<_K,_Ty,_Pr,_A> &)' : could not deduce template argument for 'const
     class std::multimap<_K,_Ty,_Pr,_A> &' from 'const class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >'
            c:\program files\microsoft visual studio\vc98\include\functional(86) : while compiling class-template member function 'bool __thiscall std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::opera
    tor ()(const class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &,const class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &) const'
    c:\program files\microsoft visual studio\vc98\include\functional(86) : error C2784: 'bool __cdecl std::operator <(const class std::map<_K,_Ty,_Pr,_A> &,const class std::map<_K,_Ty,_Pr,_A> &)' : could not deduce template argument for 'const class std
    ::map<_K,_Ty,_Pr,_A> &' from 'const class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >'
            c:\program files\microsoft visual studio\vc98\include\functional(86) : while compiling class-template member function 'bool __thiscall std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::opera
    tor ()(const class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &,const class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &) const'
    c:\program files\microsoft visual studio\vc98\include\functional(86) : error C2784:...
    Je n'ai pas précisé que je travaillais sur une appli MFC. Ca peut avoir une influence?

    Merci

  5. #5
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Je ne dispose pas de visual studio pour l'instant, mais, essaye peut être de forcer la création d'une chaine de caractères sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bonjour[string("toto")]=2;
    car, avec Gcc, il n'y a aucun problème (par contre, il me semble que le problème a déjà été abordé sur le forum...)

    Ceci dit, mon avis personnel est que, quelque part, l'usage de l'opérateur [] est assez malheureux en ce qui concerne les std::map, ne serait-ce parce qu'il a la double sémantique de recherche et d'insertion d'un élément, l'insertion s'effuant "automatiquement" si l'élément recherché n'est pas présent.

    Pour cette raison, je préfère avoir recours aux fonction insert et find:
    bonjour.insert(std::make_pair("titi",2));
    cout<<bonjour.find("titi")->second;
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Bonjour,
    Quelle version de visual utilises-tu ?

  7. #7
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Ceci dit, mon avis personnel est que, quelque part, l'usage de l'opérateur [] est assez malheureux en ce qui concerne les std::map, ne serait-ce parce qu'il a la double sémantique de recherche et d'insertion d'un élément, l'insertion s'effuant "automatiquement" si l'élément recherché n'est pas présent.

    Pour cette raison, je préfère avoir recours aux fonction insert et find:
    bonjour.insert(std::make_pair("titi",2));
    cout<<bonjour.find("titi")->second;
    Si le but est d'insérer d'abord, et de rechercher ensuite (et éventuellement de modifier), il ne faut pas prendre une map, mais un vector trié, ca ira toujours plus vite.

    L'intérêt d'une map, à mon avis, c'est justement cette idée de pouvoir "soit créer soit modifier" un élément. Ca sert quand insertions, recherches et modifications d'éléments se font en ordre dispersé. Et dans ce cas, avoir une même fonction qui recherche, et, le cas échéant, modifie ou crée, c'est plus efficace (sinon, on fait le travail en double).

    Maintenant, plus j'utilise la STL, moins j'utilise les map (et jamais les multimap). En fait, leur principale utilité c'est dans des prototypes, parce que c'est facile à écrire. Dans du code sérieux, on finit presque toujours avec des vector.

    Francois

Discussions similaires

  1. Problème avec mapping via Hibernate Synchronizer
    Par meijin_ryu dans le forum JDBC
    Réponses: 2
    Dernier message: 24/06/2012, 15h48
  2. Problèmes avec map et chaînes en tant que clé
    Par oodini dans le forum SL & STL
    Réponses: 4
    Dernier message: 15/09/2008, 18h00
  3. [STL]Problème avec map
    Par mambo dans le forum SL & STL
    Réponses: 11
    Dernier message: 27/07/2006, 15h39
  4. [PERL] Problème avec map
    Par LE NEINDRE dans le forum Langage
    Réponses: 9
    Dernier message: 05/10/2005, 09h48
  5. Problème avec memory mapping
    Par gemai dans le forum C
    Réponses: 13
    Dernier message: 04/07/2003, 09h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo