2010-06-21 12 views
5

En el programa a continuación, intento leer cada línea de un archivo en una cadena, descomponer la cadena y mostrar las palabras individuales. El problema que estoy enfrentando es, el programa ahora muestra solo la primera línea en el archivo. No entiendo por qué está pasando esto?Problema al utilizar getline y strtok juntos en un programa

#include<iostream> 
#include<string> 
#include<fstream> 
#include<cstdio> 
using namespace std; 

int main() 
{ 
    ifstream InputFile("hello.txt") ; 
    string store ; 
    char * token; 

    while(getline(InputFile,store)) 
    { 
     cout<<as<<endl; 
     token = strtok(&store[0]," "); 
     cout<<token; 
     while(token!=NULL) 
     { 
     token = strtok(NULL," "); 
     cout<<token<<" "; 
     } 

    } 

} 

Respuesta

3

Soy nuevo en C++, pero creo que un enfoque alternativo podría ser:

while(getline(InputFile, store)) 
{ 
    stringstream line(store); // include <sstream> 
    string token;   

    while (line >> token) 
    { 
     cout << "Token: " << token << endl; 
    } 
} 

Esto analizará su archivo línea por línea y lo convertirá en una línea basada en la separación de espacio en blanco (por lo tanto, esto incluye más espacios justos, como pestañas y nuevas líneas).

+0

De acuerdo: Si el caso de uso real del OP es tan simple como el que se presenta en la pregunta (división en espacios en blanco), entonces un stringstream es una muy buena idea. –

2

Bueno, aquí hay un problema. strtok() toma una cadena terminada en nulo, y los contenidos de un std::string no son necesariamente terminados en nulo.

Puede obtener una cadena terminada en cero de un std::string llamando c_str() en él, pero esto devuelve un const char* (es decir, la cadena no es modificable). strtok() toma char* y modifica la cadena cuando se llama.

Si realmente desea utilizar strtok(), a continuación, en mi opinión, la opción más limpia sería copiar los caracteres de la std::string en un std::vector y el nulo por terminado el vector:

std::string s("hello, world"); 
std::vector<char> v(s.begin(), s.end()); 
v.push_back('\0'); 

Ahora puede utilizar el contenido del vector como una cadena terminada en nulo (usando &v[0]) y pasarlo a strtok().

Si puede usar Boost, le recomiendo usar Boost Tokenizer. Proporciona una interfaz muy limpia para tokenizar una cadena.

+1

Me pregunto por qué la votación negativa; Pensé en usar un vector de contigüidad garantizada. – dreamlax

+1

Probablemente sea porque vio que tenías 30.8k puntos de repetición, 3 estrellas de oro, 75 de plata y todo el bronce y pensaste que podrías usar un voto negativo. – sashang

0

Lo que James McNellis dice es correcto.

Para una solución rápida (aunque no el mejor), en lugar de

string store 

uso

const int MAX_SIZE_LINE = 1024; //or whatever value you consider safest in your context. 
char store[MAX_SIZE_LINE];