Question

I am compiling the following code under Microsoft Visual Studio 2013

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    ifstream in("filename.txt");
    int n;
    while (!in.eof()) {
        in >> n;
        cout << n << endl;
    }
    return 0;
}

filename.txt contains:

4
 

note: the second line is empty line.

I am getting this output:

4
4

My question is: Why 4 is duplicated in the output when I add trailing spaces or empty lines to the end of the file? and why eof is not working properly in this case?

Was it helpful?

Solution

Using !eof(), !fail(), !bad(), or !good(), is invariably the wrong way to condition your input. The point is to perform the extraction first, and then check if succeeded. If you do the former, you'll almost always get the problems you are experiencing.

The first extraction into n obtained 4 from the stream. After it found the newline it stopped and you printed the value of n. When the second loop executed, the extractor cleared the leading whitespace from the stream (meaning the newline after 4), found the end of the stream and set eofbit. Since no characters were extracted, it also set failbit. When you attempted to print the value again, all you were seeing was the result of the previous input operation.

This isn't the right way to perform a read. You have to do it before checking the stream. This is how it is commonly done:

while (in >> n)
{
    std::cout << n << std::endl;
}

After the read is performed, operator bool() will be invoked on the stream, which will access its stream state and determine if the extraction succeeded. If it did, only then will the loop body execute.

OTHER TIPS

You aren't checking the state of the operation. Even if in >> n; sets a status of fail (so n was not set to a new value), you perform the next line. See http://www.cplusplus.com/doc/tutorial/files/ or http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/ or similar. Your file has an empty line before the eof, so you run the code in the while loop twice.

Here's what happens during the above code execution:

1st loop iteration:
read 4 into n
output n (4)

2nd loop iteration:
read EOF
(here there is no test for EOF)
output n (4)

3rd loop iteration (doesn't happen, because EOF was read during the last read)

You should be testing the state of in in your loop condition:

while (in >> n)
{
    // all is good, carry on
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top