Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing stream.good() or !stream.eof() reads last line twice [duplicate]

Tags:

c++

iostream

Possible Duplicate:
Why is iostream::eof inside a loop condition considered wrong?

I have the following piece of code:

ifstream f("x.txt");
string line;
while (f.good()) {
  getline(f, line);
  // Use line here.
}

But this reads the last line twice. Why does this happen and how do I fix it?

Something very similar happens with:

ifstream f("x.txt");
string line;
while (!f.eof()) {
  getline(f, line);
  // Use line here.
}
like image 530
Prabhu Avatar asked Dec 01 '10 12:12

Prabhu


3 Answers

You very, very rarely want to check bad, eof, and good. In particular for eof (as !stream.eof() is a common mistake), the stream currently being at EOF does not necessarily mean the last input operation failed; conversely, not being at EOF does not mean the last input was successful.

All of the stream state functions – fail, bad, eof, and good – tell you the current state of the stream rather than predicting the success of a future operation. Check the stream itself (which is equivalent to an inverted fail check) after the desired operation:

if (getline(stream, line)) {
  use(line);
}
else {
  handle_error();
}

if (stream >> foo >> bar) {
  use(foo, bar);
}
else {
  handle_error();
}

if (!(stream >> foo)) {  // operator! is overloaded for streams
  throw SomeException();
}
use(foo);

To read and process all lines:

for (std::string line; getline(stream, line);) {
  process(line);
}

Pointedly, good() is misnamed and is not equivalent to testing the stream itself (which the above examples do).

like image 143
Fred Nurk Avatar answered Nov 06 '22 06:11

Fred Nurk


Just use

ifstream f("x.txt");
while (getline(f, line)) {
    // whatever
}

This is the idiomatic way to write such a loop. I've not been able to reproduce the error (on a Linux machine).

like image 21
Fred Foo Avatar answered Nov 06 '22 07:11

Fred Foo


It didn't read the last line twice but because it failed to read when it reached eof, your string line has the value it had previously.

That is because f is no longer "good" when it has read EOF, not when it is about to read it.

like image 3
CashCow Avatar answered Nov 06 '22 06:11

CashCow