2012-03-30 4 views
6

следующий код не ведет себя так, как я ожидал бы. Пожалуйста, помогите мне понять, как это работает.алгоритм копирования с 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; 
} 

Мой заказ оператор >> называется два раза, но я бы ожидать, что она будет вызываться только один раз, так как содержание:

Джон: сорок: 21-5821-0

+1

Как вы знаете, что это называется дважды? Проверено в отладчике? Вы получаете две записи в векторе? Если последнее, обе записи одинаковы? –

+1

+1, с той же проблемой недавно ... по какой-то причине, увеличение итератора в коде 'copy' вызывало чтение, а не разыменование, поэтому оно выполняет одно чтение слишком много. Тем не менее, ваш 'operator >>' должен проверить состояние после первых двух операций getline'! –

+0

Бесполезно беспокоиться о коде ввода-вывода, который не проверяет возвращаемые значения. Вы всегда должны * проверять возвращаемые значения операций ввода-вывода. –

ответ

3

В общем, для чтения во весь файл, вы читаете до тех пор, пока чтение не завершится с ошибкой. Тогда вы знаете, что что-то пошло не так, или вы получили их все. В любом случае, вы не можете знать, что достигли конца файла, пока не прочитаете. Поскольку первый успешно, он должен попробовать второй раз, чтобы узнать, есть ли второй элемент. Psudocode для этого

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

Также обратите внимание, что это «идиоматическое» способ чтения в целом файле значений. Если вы проверяете eof, fail, или bad, вы, вероятно, ошибаетесь.

Это говорит о том, что ваша функция istream& operator>>(istream& is, user& s) в порядке. Во второй раз, когда он вызывается, первый getline потерпит неудачу, установив поток в плохое состояние (eof), следующие два getline s также потерпят неудачу, и он вернет поток, и все будет работать отлично. Просто помните, что любая или все эти переменные могут содержать полную бессмыслицу, поскольку чтение не удалось.