2012-03-30 49 views
6

mã sau đây không hoạt động như tôi mong đợi. Xin hãy giúp tôi hiểu nó hoạt động ra sao.thuật toán sao chép với 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; 
} 

điều hành tùy chỉnh của tôi >> được gọi là hai lần nhưng tôi mong chờ nó được gọi là chỉ một lần vì các nội dung bao gồm:

John: bốn mươi: 21-5821-0

+1

Làm thế nào để bạn biết nó được gọi là hai lần? Đã kiểm tra trong trình gỡ lỗi? Bạn nhận được hai mục trong vectơ? Nếu cuối cùng, cả hai mục đều giống nhau không? –

+1

+1, đã có cùng một vấn đề gần đây ... vì một lý do nào đó, việc tăng iterator trong mã 'copy' đã gây ra việc đọc, thay vì dereferencing, do đó nó thực hiện một lần đọc quá nhiều. Điều đó nói rằng, 'toán tử >>' của bạn cần phải kiểm tra trạng thái sau hai hoạt động 'getline' đầu tiên! –

+0

Thật vô nghĩa khi lo lắng về mã I/O không kiểm tra các giá trị trả lại. Bạn phải * luôn luôn * kiểm tra giá trị trả về của các hoạt động I/O. –

Trả lời

3

Nói chung, để đọc toàn bộ tệp, bạn đọc cho đến khi đọc không thành công. Sau đó, bạn biết một cái gì đó đã đi sai, hoặc bạn có tất cả. Dù bằng cách nào, bạn không thể biết bạn đã đến cuối tập tin cho đến khi bạn không đọc được. Kể từ khi người đầu tiên thành công, nó phải cố gắng một lần thứ hai, để tìm ra nếu có một yếu tố thứ hai. Mã psudocode cho điều này là

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

Cũng lưu ý rằng đây là cách "thành ngữ" để đọc trong toàn bộ tệp giá trị. Nếu bạn đang kiểm tra eof, fail hoặc bad, mã của bạn có thể là sai.

Điều đó nói rằng, chức năng istream& operator>>(istream& is, user& s) của bạn là tốt. Lần thứ hai nó được gọi là, getline đầu tiên sẽ không thành công, thiết lập luồng thành trạng thái xấu (eof), hai số getline s tiếp theo cũng sẽ không thành công và sẽ trả về luồng và mọi thứ hoạt động hoàn hảo. Chỉ cần nhớ rằng bất kỳ hoặc tất cả các biến đó có thể giữ vô nghĩa hoàn toàn, vì đọc không thành công.