C++ map+count

velderama Messages postés 199 Date d'inscription   Statut Membre Dernière intervention   -  
sebsauvage Messages postés 32893 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

velderama Messages postés 199 Date d'inscription   Statut Membre Dernière intervention   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
Pacorabanix Messages postés 3248 Date d'inscription   Statut Membre Dernière intervention   663
 
https://www.developpez.net/forums/f761/c-cpp/cpp/bibliotheques/sl-stl/ c'est un bon forum pour ton problème si personne ne te répond ici.


EDIT : erf tu y es déjà ;) dsl
0
mamiemando Messages postés 33778 Date d'inscription   Statut Modérateur Dernière intervention   7 884
 
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
velderama Messages postés 199 Date d'inscription   Statut Membre Dernière intervention   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
sebsauvage Messages postés 32893 Date d'inscription   Statut Modérateur Dernière intervention   15 662
 
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
velderama Messages postés 199 Date d'inscription   Statut Membre Dernière intervention   10
 
c'est map il me semble l'equivalent du hashtable en c++
0
sebsauvage Messages postés 32893 Date d'inscription   Statut Modérateur Dernière intervention   15 662 > velderama Messages postés 199 Date d'inscription   Statut Membre Dernière intervention  
 
ah pardon j'avais lu trop vite, oui tu as utilisé map.
0