2011-09-16 24 views
9

Como mi aprendizaje, estoy tratando de usar C++ ifstream y su operador >> para leer datos de un archivo de texto usando el código a continuación. El archivo de texto outdummy.txt tiene las siguientes contenidos:Usando C++ ifstream extraction operator >> para leer datos formateados desde un archivo

just dummy 
Hello ofstream 
555 

Mis preguntas es cómo leer los datos CHAR presentes en el archivo en una matriz de caracteres o una cadena. Cómo hacer esto usando el operador ifstream :: >> en el código a continuación.

#include <iostream> 
#include <fstream> 

int main() 
{ 
    int a; 
    string s; 
    char buf[100]; 
    ifstream in("outdummy.txt",ios_base::in); 


    in.operator>>(a); //How to read integer? How to read the string data.?? 

    cout << a; 

    in.close(); 
    getchar(); 
    return 0; 
} 
+2

Su ejemplo es incorrecto; ni siquiera "lees el entero correctamente". De hecho, esa línea falla y 'a' no cambia, pero por alguna razón ya la inicializaste al valor esperado, por lo que te has vendado los ojos. –

+0

@Kerrek tiene razón. Y es [provisto] (http://stackoverflow.com/questions/7443787/using-c-ifstream-extraction-operator-to-read-formatted-data-from-a-file/7443877#7443877) el correcto y fácil para usar la solución: 'getline' con' string'. –

+1

¿Por qué 'char []'? ¿Por qué no 'std :: string'? –

Respuesta

14

Si desea utilizar una entrada formateada, debe saber de antemano qué datos esperar y leerlos en variables del tipo de datos correspondiente. Por ejemplo, si se sabe que el número es siempre el quinto modo, como en el ejemplo, se puede hacer esto:

std::string s1, s2, s3, s4; 
int n; 

std::ifstream in("outdummy.txt"); 

if (in >> s1 >> s2 >> s3 >> s4 >> n) 
{ 
    std::cout << "We read the number " << n << std::endl; 
} 

Por otro lado, si se sabe que el número es siempre en la tercera línea, por sí mismo:

std::string line; 

std::getline(in, line); // have line 1 
std::getline(in, line); // have line 2 
std::getline(in, line); // have line 3 

std::istringstream iss(line); 

if (iss >> n) 
{ 
    std::cout << "We read the number " << n << std::endl; 
} 

como se puede ver, para leer un token como una cadena, que acaba de transmitir en un std::string. Es importante recordar que el operador de entrada formateado trabaja token por token, y tokens están separados por espacios en blanco (espacios, pestañas, nuevas líneas). La elección fundamental habitual es si procesa un archivo completamente en tokens (primera versión) o línea por línea (segunda versión). Para el procesamiento línea por línea, primero usa getline para leer una línea en una cadena, y luego usa una secuencia de cadenas para tokenizar la cadena.


Una palabra acerca de la validación: No se puede saber si una extracción con formato realmente tener éxito, porque eso depende de los datos de entrada. Por lo tanto, debe siempre verificar si una operación de entrada tuvo éxito, y cancelar el análisis si no lo hace, porque en caso de falla sus variables no contendrán los datos correctos, pero no tiene forma de saberlo más tarde. Así que siempre decirlo así:

if (in >> v) { /* ... */ }   // v is some suitable variable 
else { /* could not read into v */ } 

if (std::getline(in, line)) { /* process line */ } 
else { /* error, no line! */ } 

La última construcción se utiliza generalmente en un bucle while, para leer un archivo línea por línea entera:

while (std::getline(in, line)) { /* process line */ } 
+0

Gracias por una respuesta detallada. – goldenmean

2
  1. ifstream tiene ios_base::in por defecto. No necesita especificarlo.
  2. operator>> se puede invocar directamente como operador: in >> a.
  3. La lectura de cadenas es la misma: in >> s, pero la advertencia es que está delimitada por espacios en blanco, por lo que se leerá "solo" por sí mismo, sin "ficticio".
  4. Si quiere leer líneas completas, use std::getline(in, s).
1

Puesto que usted ha elegido utilizar C-secuencias, se puede utilizar el método getline de su objeto ifstream (no std::getline() que trabaja con std::string s), lo que le permitirá especificar la C-secuencia y un tamaño máximo para el buffer

Sobre la base de lo que tenía, y la adición de un tampón adicional para la segunda línea:

char buf[100]; 
char buf2[100]; 

in.getline(buf,sizeof(buf)); 
in.getline(buf2,sizeof(buf2)); 
in >> a; 

Sin embargo, como ha propuesto el otro cartel, intente utilizar el std::string y sus métodos, que le hará la vida más fácil .

+1

Ewwww. C arrays. Números mágicos. :-( –

+0

@Kerrek Predicando al coro, pero estoy tratando de adaptarlo a su ejemplo. – jonsca

+0

es justo, pero creo que si alguien sugiere 'in.operator >> (a)' en primer lugar, es hora para una muda de ropa :-) –

0

Puede leer los contenidos del archivo y utilizar un Finite State Machine para analizar.

Ejemplo:

void Parse(const char* buffer, size_t length); 
size_t GetBufferSize(); 

size_t bufferSize = GetBufferSize(); 
char* buffer = new char[bufferSize]; 

std::ifstream in("input.txt"); 
while(in.getline(buffer, bufferSize)) { 
    Parse(buffer, in.gcount()); 
} 

Alternativamente, se puede utilizar una herramienta como Flex para escribir su analizador.

+0

¿Asigna dinámicamente una matriz de caracteres? ¿Seriamente? Algo malo con 'std :: string'? –

+0

Utilicé una matriz de caracteres dinámicamente asignada para ser coherente con el ejemplo incluido en la pregunta. Por supuesto, sería más adecuado utilizar un contenedor como 'string',' rope' o '' en lugar de una matriz char en el código de producción y debería haberlo mencionado. – npclaudiu

+0

La pregunta no asignó dinámicamente una matriz 'char'. –

Cuestiones relacionadas