2009-03-16 10 views
7

Sto lavorando ad un incarico in cui dovrei leggere un file e contare il numero di linee e allo stesso tempo contare le parole in esso. Ho provato una combinazione di getline e strtok all'interno di un ciclo while, che non ha funzionato.Come dividere un file di testo in parole?

file: example.txt (il file da leggere).

Ciao, ciao che piacevole sorpresa.
Benvenuti in questo posto.
Possa trascorrere un piacevole soggiorno qui.
(3 righe e alcune parole).

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

hai bisogno di dire altro che "non ha funzionato". Dicci quale errore ottieni, o la cosa SPECIFICA che il tuo programma fa in modo diverso da come ti aspetti, quindi fai una domanda specifica. Non eseguiremo il debug o riscriveremo i compiti per te. – Blorgbeard

+17

Ecco alcuni esempi dei seguenti: http://www.codeproject.com/KB/recipes/Tokenizer.aspx Sono molto efficienti e alquanto eleganti. La libreria String Toolkit rende l'elaborazione di stringhe complessa in C++ semplice e facile. –

risposta

0

Provare a spostare la sua dichiarazione cout<<t2<<end; nel vostro ciclo while.

Ciò dovrebbe rendere il codice sostanzialmente funzionante.

Si potrebbe voler vedere this similar post per altri approcci.

0

Ci sono esempi come questo pubblicati su Internet. Ecco un programma di parole di conteggio che ho scritto quando ero al liceo. Usalo come punto di partenza. Altre cose che vorrei sottolineare sono:

std :: stringstream: tu std :: ottieni l'intera riga, quindi usa std :: stringstream per tagliarlo in pezzi più piccoli e renderlo più semplice. È possibile ottenere l'intera riga utilizzando std :: getline e inserendolo in una std :: string, che può quindi passare a std :: stringstream.

Ancora una volta, questo è solo un esempio e non farà esattamente quello che vuoi, dovrai modificarlo tu stesso per farlo fare quello che vuoi che faccia!

#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

Ciao, Grazie, Blorgbeard, Reed e X-Istence per le risposte rapide. Non devo solo analizzare la linea, ma anche tenere traccia della linea Numero. L'affermazione del problema è di creare un elenco di parole con le line-nos in cui appaiono. –

+0

Ravi: in cui il codice che ti ho appena dato ti porterà a metà strada lì. Non siamo qui per fare i compiti per te! –

+0

Oh No! Non era mia intenzione. Sto avendo problemi con la prima parte. Una volta risolto, intendo fare il resto da solo. –

5

Appena capito bene !! Appena rimosso tutto il codice non necessario.

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; 
} 

proposito la dichiarazione problema originale è stato quello di creare un programma di indice che avrebbe accettato un file utente e creare una linea indice di tutte le parole.

+0

Si prega di non utilizzare strtok. Tornerà a morderti non appena avrai bisogno di scrivere codice multi-thread. Una buona sostituzione con C++ standard è std :: istringstream. – Tom

0

Se è possibile utilizzare le librerie Boost, vorrei suggerire di usare boost::tokenizer:

Il pacchetto Tokenizer spinta fornisce un modo flessibile e facile da usare per rompere di una stringa o un altro carattere sequenza in un serie di token. Di seguito è riportato un semplice esempio che sostituirà una frase in .

// 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

Non ho provato la compilazione di questo, ma qui è un'alternativa che è quasi semplice come utilizzare Boost, ma senza la dipendenza supplementare.

#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 Ecco come lo farei. Ora basta inserire i contatori ed è fatto. – Frank

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

Non dimenticate di includere questo:

<iterator>