C++ map+count

velderama Messages postés 203 Statut Membre -  
sebsauvage Messages postés 33284 Date d'inscription   Statut Modérateur Dernière intervention   -
Bonjour a tous,

j'ai une map map<string,int > mymap que j'ai rempli avec les mots d'un fichier et j'aimerai interdire l'enregistrement dans le map des mots qui ne sont pas uniques comme ceci :

map<string, int>::size_type size;

map<string,int > mymap;
{
while(getline(fichier,line)){
...
size=mymap.count(mot);
if(count>=1) mymap.erase(mot);
else mymap.insert(make_pair(mot,position));
...
}//fin while

}
toutefois j'ai des problemes pour le premier getline vu que il y'aura pas encore de mot dans le map et donc il enleverra les suivants mots identiques mais pas la premiere ligne ! comment dois-je faire?
merci d'avance

3 réponses

  1. velderama Messages postés 203 Statut Membre 10
     
    J'ai vu dans la librairie un conteneur vector avec notamment une methode size qui me permettrait de faire le test suivant : si la taille est superieur a 1 alors de suprimmer le mot

    map<string, vector<int> > mots;
    string line;
    int pos=0;
    for(unsigned no_line = 0;std::getline(ifs,line);++no_line){

    unsigned beg = 0;//debut mot
    unsigned end = 1;//fin mot
    for(unsigned no_mot=0;end < line.size();++no_mot){

    for(;end < line.size() && !is_delim(line[end]);++end);

    std::string mot(line,beg,end-beg);
    pos=pos+beg;
    if(mot.size()>=3 ){
    mots.insert(make_pair(mot,pos));
    }

    beg = end + 1;
    end = beg + 1;
    }//for..line.size()
    }
    Puis je fais :---->

    /*On enleve les mots "non uniques" */

    map<string,vector<int> >::const_iterator
    mots_it (mots.begin()),
    mots_end(mots.end());

    for(;mots_it!=mots_end;++mots_it){
    const string & mot_cur = mots_it->first;
    vector<int> & nbelement = mots_it->second;
    if((nbelement.size())>1) mots.erase(mots_it);
    }
    ifs.close();
    mais il y'a un bug :
    invalid initialization of reference of type 'std::vector<int, std::allocator<int> >&' from expression of type 'const std::vector<int, std::allocator<int> >'

    ???
    0
  2. mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   7 944
     
    Signification du message d'erreur

    Ton erreur vient du fait que tu parcours mots avec un const_iterator (qui garantit que tu ne vas pas modifier les éléments sur lesquels tu itères). Or :
    std::vector<int> & nbelement 

    ne garantit pas la constance de ces éléments contrairement à un
    const std::vector<int> & nbelement 


    Attention !!

    Vu que tu utilises un erase tu ne peux donc pas utiliser un const_iterator car la map est modifiée. De plus, effacer un élément d'un std::map ou d'un std::set invalide les iterators donc même en virant les const ca ne marchera pas.

    Correction du code ?

    Au niveau du code je pense qu'il y a un vrai problème de compréhension au niveau de la ligne :
    mots.insert(make_pair(mot,pos)); 

    Si tu veux stocker les positions des mots de longueurs 3 ou plus :
    std::map<string, std::set<unsigned> > mots;
    std::string line;
    unsigned pos=0;
    for(unsigned no_line = 0;std::getline(ifs,line);++no_line){
      unsigned beg = 0;//debut mot
      unsigned end = 1;//fin mot
      for(unsigned no_mot=0;end < line.size();++no_mot){
        for(;end < line.size() && !is_delim(line[end]);++end);
        std::string mot(line,beg,end-beg);
        pos=pos+beg;
        if(mot.size()>=3 ){
          mots[mot].insert(pos);
        } 
      }
    }

    Pour que tout le monde puisse t'aider il est important que tu mettes le code complet, si j'ai pu raccrocher c'est uniquement parce que j'ai répondu à ton précédent message. Par rapport à ça quand je mets des std:: ou des unsigned plutôt que des int c'est qu'il y a une raison, donc merci de les laisser :-)

    Bonne chance
    0
    1. velderama Messages postés 203 Statut Membre 10
       
      Ok, voila tout le code

      #include <iostream>
      #include <fstream>
      #include <string>
      #include <map>
      #include <set>

      using namespace std;

      inline bool is_delim(char c){
      return !isalpha(c);
      }
      /***********************main**************************************/
      int main(int argc, char *argv[]){

      const char *filename = argv[1];
      const char *filename2 = argv[2];
      std::ifstream ifs(argv[1]);
      std::ifstream if2s(argv[2]);

      map<string, vector<int> > mots;
      string line;
      unsigned pos=0;
      for(unsigned no_line = 0;std::getline(ifs,line);++no_line){

      unsigned beg = 0;
      unsigned end = 1;
      for(unsigned no_mot=0;end < line.size();++no_mot){

      for(;end < line.size() && !is_delim(line[end]);++end);

      std::string mot(line,beg,end-beg);//recuperation du mot
      pos=pos+beg;
      if(mot.size()>=3 ){
      std::cout << "\tajoute le mot[" << mot << "]position = "
      << pos << std::endl;

      mots[mot].insert(pos);
      }

      beg = end + 1;
      end = beg + 1;
      }
      }


      /*On enleve les doublons*/

      map<string,vector<int> >::iterator
      mots_it (mots.begin()),
      mots_end(mots.end());
      for(;mots_it!=mots_end;++mots_it){
      const std::string & mot_cur = mots_it->first;
      vector<int> &nbelement = mots_it->second;
      if((nbelement.size())>1) mots.erase(mots_it);
      }
      ifs.close();

      return 0;

      }//main
      0
  3. sebsauvage Messages postés 33284 Date d'inscription   Statut Modérateur Dernière intervention   15 684
     
    Et pourquoi pas plutôt une hashtable ? (aussi parfois appellé dictionnaire).

    Elle assure l'unicité des éléments.

    (Je ne sais plus comment elle s'appelle en STL...)
    0
    1. velderama Messages postés 203 Statut Membre 10
       
      c'est map il me semble l'equivalent du hashtable en c++
      0
      1. sebsauvage Messages postés 33284 Date d'inscription   Statut Modérateur Dernière intervention   15 684 > velderama Messages postés 203 Statut Membre
         
        ah pardon j'avais lu trop vite, oui tu as utilisé map.
        0