Testing stream.good() or !stream.eof() reads last line twice [duplicate]
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.
}
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).
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).
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.
精彩评论