2009-03-16 22 views
7

Estoy trabajando en una tarea en la que se supone que debo leer un archivo y contar el número de líneas y al mismo tiempo contar las palabras en él. Intenté una combinación de getline y strtok dentro de un ciclo while, que no funcionó.¿Cómo dividir un archivo de texto en palabras?

file: example.txt (el archivo para ser leído).

Hola, hola qué agradable sorpresa.
Bienvenido a este lugar.
Que tengas una estancia agradable aquí.
(3 líneas y algunas palabras).

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

que necesita decir más que "no funcionó". Díganos qué error obtiene, o lo ESPECÍFICO que su programa hace de manera diferente a lo que esperaba, luego formule una pregunta específica. No depuraremos ni reescribiremos su tarea por usted. – Blorgbeard

+17

¿Qué tal algunos de los ejemplos de los siguientes: http://www.codeproject.com/KB/recipes/Tokenizer.aspx Son muy eficientes y algo elegantes. La biblioteca String Toolkit hace que el complejo procesamiento de cadenas en C++ sea simple y fácil. –

Respuesta

0

Trate de mover su estado de cout<<t2<<end; en su bucle while.

Eso debería hacer que su código sea básicamente funcional.

Es posible que desee ver this similar post para otros enfoques.

0

Hay ejemplos como este publicados en Internet. Aquí hay un programa de recuento de palabras que escribí cuando estaba en la escuela secundaria. Úselo como punto de partida. Otras cosas que me gustaría señalar son:

std :: stringstream: usas la línea completa, luego usas std :: stringstream para dividirla en trozos más pequeños y juntarla. Puede obtener toda la línea usando std :: getline e ingresarla en std :: string, que luego puede pasar a std :: stringstream.

Una vez más, esto es solo un ejemplo y no hará exactamente lo que usted quiere que haga, ¡tendrá que modificarlo usted mismo para que haga lo que usted quiere que haga!

#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

Hola, Gracias, Blorgbeard, Reed y X-Istence para las respuestas rápidas. Necesito no solo analizar la línea, sino también hacer un seguimiento de la líneaNos. El enunciado del problema es hacer una lista de palabras con los line-nos en los que aparecen. –

+0

Ravi: en el que el código que acabo de darle te llevará a la mitad del camino. ¡No estamos aquí para hacer tu tarea por ti! –

+0

¡Oh, no! Esa no era mi intención. Estoy teniendo problemas con la primera parte. Una vez que se solucione, pretendo hacer el resto por mi cuenta. –

5

Just got this right !! Acaba de eliminar todo el código innecesario.

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

Por cierto, el planteamiento del problema original era crear un programa de índice que acepte un archivo de usuario y crear una línea de índice de todas las palabras.

+0

Por favor, no use strtok. Volverá a morderte tan pronto como necesites escribir un código de subprocesos múltiples. Un buen reemplazo con C++ estándar es std :: istringstream. – Tom

0

Si puede utilizar bibliotecas Boost, sugeriría utilizar boost::tokenizer:

El paquete Tokenizer impulso proporciona una manera flexible y fácil de usar romper de una cadena u otro carácter secuencia en una serie de tokens A continuación se muestra un ejemplo simple que dividirá una frase en palabras.

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

No he intentado compilar esto, pero aquí es una alternativa que es tan simple como usar Boost, pero sin la dependencia adicional.

#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 Así es como lo haría. Ahora solo inserta los contadores y listo. – Frank

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

No se olvide de incluir lo siguiente:

<iterator> 
Cuestiones relacionadas