2012-03-30 12 views
6

el siguiente código no se comporta como esperaba. Por favor, ayúdame a entender cómo funciona.algoritmo de copia con ifstream

#include <algorithm> 
#include <iterator> 
#include <fstream> 
#include <vector> 
#include <string> 
using namespace std; 

struct user 
{ 
     string name; 
     string age; 
     string id; 
}; 

istream& operator>>(istream& is, user& s) 
{ 
     getline(is, s.name, ':'); 
     getline(is, s.age, ':'); 
     getline(is, s.id); 

     return is; 
} 

int main(int argc, char* argv[]) 
{ 
     ifstream file("file.txt"); 
     vector<user> vec; 
     copy(istream_iterator<user>(file), istream_iterator<user>(), back_inserter(vec)); 

     return 0; 
} 

Mi operadora personalizada >> se llama dos veces, pero yo esperaría que sea llamado una sola vez ya que los contenidos son:

John: cuarenta: 21-5821-0

+1

¿Cómo sabes que se llama dos veces? Check-in depurador? ¿Obtienes dos entradas en el vector? Si es el último, ¿las dos entradas son las mismas? –

+1

+1, tuvo el mismo problema recientemente ... por alguna razón, el incremento del iterador en el código 'copy' estaba causando la lectura, en lugar de la desreferenciación, por lo que realiza una lectura demasiada. Dicho esto, su 'operador >>' necesita verificar el estado después de las dos primeras operaciones 'getline'! –

+0

No tiene sentido preocuparse por el código de E/S que no verifica los valores devueltos. Debe * siempre * verificar los valores de retorno de las operaciones de E/S. –

Respuesta

3

En general, para leer en un archivo completo, lo lee hasta que falla una lectura. Entonces sabes que algo salió mal, o los tienes todos. De cualquier manera, no puede saber que llegó al final del archivo hasta que no puede leer. Como el primero tiene éxito, debe intentarlo una segunda vez, para descubrir si hay un segundo elemento. El psudocode de esto es

while(in_stream >> object) { 
    myvector.push_back(object); 
} 

También tenga en cuenta que este es el camino "idiomática" leer en un archivo completo de valores. Si está buscando eof, fail o bad, su código probablemente sea incorrecto.

Dicho esto, su función istream& operator>>(istream& is, user& s) está muy bien. La segunda vez que se invoca, el primer getline fallará y la transmisión quedará en un estado incorrecto (eof), los siguientes dos getline también fallarán, y devolverá la transmisión, y todo funciona perfectamente. Solo recuerde que cualquiera o todas esas variables pueden contener un completo sinsentido, ya que la lectura falló.