2009-03-16 12 views
7

Je travaille sur un devoir où je suis supposé lire un fichier et compter le nombre de lignes et en même temps compter les mots dedans. J'ai essayé une combinaison de getline et strtok dans une boucle while, ce qui n'a pas fonctionné.Comment diviser un fichier texte en mots?

fichier: example.txt (le fichier à lire).

Salut, bonjour quelle agréable surprise.
Bienvenue à cet endroit.
Pour que vous passiez un agréable séjour ici.
(3 lignes, et quelques mots).

Readfile.cpp

#include <iostream> 
#include <fstream> 
#include<string> 
using namespace std; 
int main() 
{ 
    ifstream in("example.txt"); 
    int count = 0; 

    if(!in) 
    { 
    cout << "Cannot open input file.\n"; 
    return 1; 
    } 

    char str[255]; 
    string tok; 
    char * t2; 

    while(in) 
    { 
    in.getline(str, 255); 
    in>>tok; 
    char *dup = strdup(tok.c_str()); 
    do 
    { 
     t2 = strtok(dup," "); 
    }while(t2 != NULL); 
    cout<<t2<<endl; 
    free (dup); 
    count++; 
    } 
    in.close(); 
    cout<<count; 
    return 0; 
} 
+0

Vous devez dire plus que "ne fonctionne pas". Dites-nous quelle erreur vous obtenez, ou la chose spécifique que votre programme fait différemment que vous attendez, puis posez une question spécifique. Nous ne débuggerons ni ne réécrirons vos devoirs pour vous. – Blorgbeard

+17

Que diriez-vous des exemples de ce qui suit: http://www.codeproject.com/KB/recipes/Tokenizer.aspx Ils sont très efficaces et peu élégante. La bibliothèque String Toolkit rend le traitement de chaînes complexe en C++ simple et facile. –

Répondre

0

Essayez de déplacer votre déclaration cout<<t2<<end; dans votre boucle while.

Cela devrait rendre votre code fondamentalement fonctionnel.

Vous voudrez peut-être voir this similar post pour d'autres approches.

0

Il existe des exemples de ce type publiés sur Internet. Voici un programme de comptes-mots que j'ai écrit lorsque j'étais au lycée. Utilisez-le comme point de départ. D'autres choses que je voudrais souligner sont:

std :: stringstream: vous std :: getline la ligne entière, puis utilisez std :: stringstream pour le couper en petits morceaux et tokenise. Vous pouvez obtenir la ligne entière en utilisant std :: getline et en l'entrant dans une chaîne std :: que vous pouvez ensuite passer à std :: stringstream.

Encore une fois, ceci n'est qu'un exemple et ne fera pas exactement ce que vous voulez faire, vous devrez le modifier vous-même pour qu'il fasse ce que vous voulez qu'il fasse!

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

// Global variables 
     std::map<std::string, int> wordcount; 
     unsigned int numcount; 

void addEntry (std::string &entry) { 
     wordcount[entry]++; 
     numcount++; 
     return; 
} 


void returnCount() { 
     double percentage = numcount * 0.01; 
     percentage = floor(percentage + 0.5f); 

     std::map<std::string, int>::iterator Iter; 

     for (Iter = wordcount.begin(); Iter != wordcount.end(); ++Iter) { 
       if ((*Iter).second > percentage) { 
         std::cout << (*Iter).first << " used " << (*Iter).second << " times" << std::endl; 
       } 
     } 

} 

int main(int argc, char *argv[]) { 
     if (argc != 2) { 
       std::cerr << "Please call the program like follows: \n\t" << argv[0] 
         << " <file name>" << std::endl; 
       return 1; 
     } 

     std::string data; 

     std::ifstream fileRead; 
     fileRead.open(argv[1]); 
     while (fileRead >> data) { 
       addEntry(data); 
     } 
     std::cout << "Total words in this file: " << numcount << std::endl; 
     std::cout << "Words that are 1% of the file: " << std::endl; 
     returnCount(); 
} 
+0

Bonjour, Merci , Blorgbeard, Reed et X-tence pour les réponses rapides. Je dois non seulement analyser la ligne, mais aussi garder trace de la ligneNos. L'énoncé du problème consiste à faire une liste de mots avec les numéros de ligne sur lesquels ils apparaissent. –

+0

Ravi: Dans lequel le code que je viens de vous donner vous mènera à mi-chemin. Nous ne sommes pas ici pour faire vos devoirs pour vous! –

+0

Oh non! Ce n'était pas mon intention. J'ai des problèmes avec la première partie seulement. Une fois cela réglé, j'ai l'intention de faire le reste par moi-même. –

5

Juste obtenu ce droit !! Juste enlevé tout le code inutile.

int main() 
{  
    ifstream in("example.txt"); 
    int LineCount = 0; 
    char* str = new char[500]; 

    while(in) 
    { 
     LineCount++; 
     in.getline(str, 255); 
     char * tempPtr = strtok(str," "); 
     while(tempPtr) 
     { 
      AddWord(tempPtr, LineCount); 
      tempPtr = strtok(NULL," ,."); 
     } 
    } 
    in.close(); 
    delete [] str; 
    cout<<"Total No of lines:"<<LineCount<<endl; 
    showData(); 

    return 0; 
} 

BTW l'énoncé du problème initial était de créer un programme d'index qui accepte un fichier utilisateur et créer une ligne index de tous les mots.

+0

Veuillez ne pas utiliser strtok. Il reviendra vous mordre dès que vous aurez besoin d'écrire du code multithread. Std :: istringstream est un bon remplacement du standard C++. – Tom

0

Si vous pouvez utiliser les bibliothèques Boost, je suggère d'utiliser boost::tokenizer:

Le boost package Tokenizer fournit une manière flexible et facile à utiliser pour briser d'une chaîne ou une autre séquence caractère dans un série de jetons. Voici un exemple simple qui va diviser une phrase en mots.

// simple_example_1.cpp 
#include<iostream> 
#include<boost/tokenizer.hpp> 
#include<string> 

int main(){ 
    using namespace std; 
    using namespace boost; 
    string s = "This is, a test"; 
    tokenizer<> tok(s); 
    for(tokenizer<>::iterator beg=tok.begin();beg!=tok.end();++beg){ 
     cout << *beg << "\n"; 
    } 
} 
3

Je ne l'ai pas essayé la compilation, mais voici une alternative qui est presque aussi simple que d'utiliser Boost, mais sans la dépendance supplémentaire.

#include <iostream> 
#include <sstream> 
#include <string> 

int main() { 
    std::string line; 
    while (std::getline(std::cin, line)) { 
    std::istringstream linestream(line); 
    std::string word; 
    while (linestream >> word) { 
     std::cout << word << "\n"; 
    } 
    } 
    return 0; 
} 
+0

+1 Voilà comment je le ferais. Maintenant insérez simplement les compteurs et c'est fait. – Frank

0
ifstream is {"my_file_path"}; 
vector<string> b {istream_iterator<string>{is},istream_iterator<string>{}}; 

Ne pas oublier d'inclure ceci:

<iterator> 
Questions connexes