Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

copy algorithm with ifstream

the following code is not behaving like I would expect. Please help me understand how it works.

#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;
}

My custom operator>> is called twice but I would expect it to be called only once because the contents are:

John:forty:21-5821-0

like image 576
flumpb Avatar asked Mar 30 '12 22:03

flumpb


1 Answers

In general, to read in an entire file, you read until a read fails. Then you know either something went wrong, or you got them all. Either way, you can't know you reached the end of the file until you fail to read. Since the first one succeeds, it must try a second time, to find out if there is a second element. The psudocode for this is

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

Also note that this is the "idiomatic" way to read in an entire file of values. If you're checking for eof, fail, or bad, you're code is probably wrong.

That said, your istream& operator>>(istream& is, user& s) function is just fine. The second time it is called, the first getline will fail, setting the stream to a bad state (eof), the next two getlines will fail as well, and it will return the stream, and everything works perfectly. Just remember that any or all of those variables may hold complete nonsense, since the read failed.

like image 105
Mooing Duck Avatar answered Nov 06 '22 04:11

Mooing Duck