2012-03-30 13 views
6

der folgende Code verhält sich nicht wie ich es erwarten würde. Bitte hilf mir zu verstehen, wie es funktioniert.kopieren Algorithmus mit 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; 
} 

Mein benutzerdefinierter Operator >> zweimal genannt, aber ich würde erwarten, dass es nur einmal aufgerufen werden, da der Inhalt:

John: vierzig: 21-5821-0

+1

Woher wissen Sie, dass es zweimal aufgerufen wird? Check-in Debugger? Sie erhalten zwei Einträge im Vektor? Sind die letzten, sind beide Einträge gleich? –

+1

+1, hatte in letzter Zeit das gleiche Problem ... Aus irgendeinem Grund verursachte der Iterator-Inkrement in dem 'copy'-Code das Lesen und nicht das Dereferenzieren, so dass ein Lesen zu viele durchgeführt wird. Das heißt, Ihr 'Operator >>' muss den Status nach den ersten beiden 'getline'-Operationen überprüfen! –

+0

Es macht keinen Sinn, sich Gedanken über den E/A-Code zu machen, der die Rückgabewerte nicht überprüft. Sie müssen * immer * die Rückgabewerte von E/A-Operationen überprüfen. –

Antwort

3

Im Allgemeinen Um eine ganze Datei einzulesen, lesen Sie, bis ein Lesevorgang fehlschlägt. Dann weißt du entweder, dass etwas schief gelaufen ist, oder du hast sie alle bekommen. In jedem Fall können Sie nicht wissen, dass Sie das Ende der Datei erreicht haben, bis Sie nicht lesen können. Da die erste erfolgreich ist, muss sie ein zweites Mal versuchen, herauszufinden, ob es ein zweites Element gibt. Die psudocode hierfür ist

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

Beachten Sie auch, dass dies die „idiomatische“ Art und Weise ist in einer ganzen Datei von Werten zu lesen. Wenn Sie nach eof, fail oder bad suchen, ist Ihr Code wahrscheinlich falsch.

Das sagte, Ihre istream& operator>>(istream& is, user& s) Funktion ist in Ordnung. Beim zweiten Aufruf wird die erste getline fehlschlagen und der Stream wird in einen schlechten Zustand versetzt (eof), die nächsten beiden getline werden ebenfalls fehlschlagen, und es wird den Stream zurückgeben, und alles funktioniert einwandfrei. Denken Sie daran, dass einige oder alle dieser Variablen möglicherweise völligen Unsinn enthalten, da das Lesen fehlgeschlagen ist.