Comptage des occurrences de chaque mot dans un fichier texte

Dans le cas d’un fichier texte volumineux comportant plusieurs chaînes, quel serait le moyen le plus efficace de lire le fichier texte et de compter le nombre d’occurrences de chaque mot en C ++? La taille du fichier texte étant inconnue, je ne peux pas utiliser un simple tableau. En outre, il y a un autre piège. Chaque ligne de ce fichier texte commence par un mot-clé de catégorie et les mots suivants représentent les caractéristiques de cette catégorie. Je dois pouvoir compter le nombre d’occurrences de chaque mot dans cette catégorie.

Par exemple:

colors red blue green yellow orange purple sky blue high clouds air empty vast big ocean wet water aquatic blue colors brown black blue white blue blue 

Avec cet exemple, je dois compter que dans la catégorie ” couleurs “, il y a 4 occurrences de ” bleu “, bien qu’il y ait 6 occurrences totales de bleu au total.

Je voudrais utiliser un stream pour lire et séparer les mots (il sépare les mots en recherchant des espaces) et les enregistre dans un dictionnaire (la méthode C ++ standard consiste à utiliser std::map ).

Voici un code documenté en C ++:

 #include  #include  // A map will be used to count the words. #include  // Will be used to read from a file. #include  // The map's key value. using namespace std; //Will be used to print the map later. template  void PrintMap(map map) { typedef std::map::iterator iterator; for (iterator p = map.begin(); p != map.end(); p++) cout << p->first << ": " << p->second << endl; } int main(void) { static const char* fileName = "C:\\MyFile.txt"; // Will store the word and count. map wordsCount; { // Begin reading from file: ifstream fileStream(fileName); // Check if we've opened the file (as we should have). if (fileStream.is_open()) while (fileStream.good()) { // Store the next word in the file in a local variable. ssortingng word; fileStream >> word; //Look if it's already there. if (wordsCount.find(word) == wordsCount.end()) // Then we've encountered the word for a first time. wordsCount[word] = 1; // Initialize it to 1. else // Then we've already seen it before.. wordsCount[word]++; // Just increment it. } else // We couldn't open the file. Report the error in the error stream. { cerr << "Couldn't open the file." << endl; return EXIT_FAILURE; } // Print the words map. PrintMap(wordsCount); } return EXIT_SUCCESS; } 

Sortie:

air: 1
aquatique: 1
grand: 1
noir: 1
bleu: 6
marron: 1
nuages: 1
couleurs: 2
vide: 1
vert: 1
haute: 1
océan: 1
orange: 1
violet: 1
rouge: 1
ciel: 1
vaste: 1
eau: 1
humide: 1
blanc: 1
jaune: 1

Tokenize les mots et les stocker en tant que paires clé-valeur.

MISE À JOUR: J’ai réalisé que j’avais mal interprété la question. Le code suivant doit séparer et compter par catégories:

 #include  #include  #include  #include  using namespace std; int main() { ifstream file; file.open("path\\to\\text\\file"); if(!file.is_open()) return 1; map > categories; while(file.good()) { ssortingng s; getline(file, s); int pos = s.find_first_of(' '); if(pos < 0) continue; string word = s.substr(0, pos); string category = word; s = s.erase(0, pos+1); while(s.size() > 0) { pos = s.find_first_of(' '); if(pos < 0) pos = s.size(); string word = s.substr(0, pos); if(word != "") categories[category][word]++; s = s.erase(0, pos+1); } } for(map >::iterator cit = categories.begin(); cit != categories.end(); ++cit) { cout << "Category - " << cit->first << endl; for(map::iterator wit = cit->second.begin(); wit != cit->second.end(); ++wit) cout << "\tword: " << wit->first << ",\t" << wit->second << endl; } return 0; } 

Mise à jour 2: Chris a demandé une modification de l'algorithme:

 #include  #include  #include  #include  using namespace std; int main() { ifstream file; file.open("D:\\Documents\\txt.txt"); if(!file.is_open()) return 1; map categories; while(file.good()) { ssortingng s; getline(file, s); int pos = s.find_first_of(' '); if(pos < 0) continue; while(s.size() > 0) { pos = s.find_first_of(' '); if(pos < 0) pos = s.size(); string word = s.substr(0, pos); if(word != "") categories[word]++; s = s.erase(0, pos+1); } } for(map::iterator wit = categories.begin(); wit != categories.end(); ++wit) cout << "word: " << wit->first << "\t" << wit->second << endl; return 0; } 

Voici une solution qui réalise votre objective déclaré. Voir en direct ici .

Il utilise std::map pour gérer le nombre de fois où une paire (catégorie, mot) se produit.

std::issortingngstream est utilisé pour diviser les données en lignes puis en mots.


SORTIE:

 (colors, black) => 1 (colors, blue) => 4 (colors, brown) => 1 (colors, green) => 1 (colors, orange) => 1 (colors, purple) => 1 (colors, red) => 1 (colors, white) => 1 (colors, yellow) => 1 (ocean, aquatic) => 1 (ocean, blue) => 1 (ocean, water) => 1 (ocean, wet) => 1 (sky, air) => 1 (sky, big) => 1 (sky, blue) => 1 (sky, clouds) => 1 (sky, empty) => 1 (sky, high) => 1 (sky, vast) => 1 

PROGRAMME:

 #include  // std::cout, std::endl #include  // std::map #include  // std::issortingngstream #include  // std::pair int main() { // The data. std::ssortingng content = "colors red blue green yellow orange purple\n" "sky blue high clouds air empty vast big\n" "ocean wet water aquatic blue\n" "colors brown black blue white blue blue\n"; // Load the data into an in-memory table. std::issortingngstream table(content); std::ssortingng row; std::ssortingng category; std::ssortingng word; const char delim = ' '; std::map, long> category_map; std::pair cw_pair; long count; // Read each row from the in-memory table. while (!table.eof()) { // Get a row of data. getline(table, row); // Allow the row to be read word-by-word. std::issortingngstream words(row); // Get the first word in the row; it is the category. getline(words, category, delim); // Get the remaining words in the row. while (std::getline(words, word, delim)) { cw_pair = std::make_pair(category, word); // Maintain a count of each time a (category, word) pair occurs. if (category_map.count(cw_pair) > 0) { category_map[cw_pair] += 1; } else { category_map[cw_pair] = 1; } } } // Print out each unique (category, word) pair and // the number of times that it occurs. std::map, long>::iterator it; for (it = category_map.begin(); it != category_map.end(); ++it) { cw_pair = it->first; category = cw_pair.first; word = cw_pair.second; count = it->second; std::cout << "(" << category << ", " << word << ") => " << count << std::endl; } }