Various sources say that using std :: istream :: eof ()
is a sign of bad code and that in particular it is wrong to write:
while (! input_stream.eof ()) {
input_stream & gt; & gt; value;
process (value);
}
What’s wrong with this code? How to write correctly?
Answer 1, authority 100%
The problem with std :: istream :: eof ()
is that it is exposed only after some read operation has been performed. Therefore, the following happens:
std :: ifstream input_stream ("empty_file.txt"); // Open an empty file
if (! input_stream.eof ()) {// eof () == false, because we haven't read anything yet
int value;
input_stream & gt; & gt; value; // Trying to read a number, but it's not there.
// Here eof () == true, but we don't check it.
std :: cout & lt; & lt; value; // Will display 0.
}
So if you do call eof ()
, then it should be done after the read operation.
However, std :: istream
objects can be converted to bool
, and each read operation returns a reference to std :: istream
. So the idiomatic code looks like this:
while (input_stream & gt; & gt; value) {
process (value);
}
Or for a line:
std :: string str;
while (std :: getline (input_stream, str)) {...}
Or for several values at once:
while (input_stream & gt; & gt; value1 & gt; & gt; value2) {...}
Here, if an error occurs while reading value1
, then all subsequent read operations (i.e. value2
) will be ignored, so you can read several values at once, and only then check the status of std :: istream
.
Answer 2, authority 7%
eof () is just a function that returns true if end of file is detected. And if someone uses it after having read the garbage somewhere where it is not needed, this is probably bad code.
For example:
char value;
if (! (input_stream.get (value))) // if the stream is in an error state
{
if (input_stream.eof ()) // was the end of file caused
{
I don’t see anything wrong here