Skip to main content

Section 11.7 End of File

What if you do not know how many tokens there are to read?
In that case we can keep reading until we encounter the end of the file. One way to detect if we have reached the end of the file is to just wait for an error. Trying to read another token once reach the end will produce an error! But we can also use the .eof() method to ask β€œare we at the End Of File yet?”. It returns true if the end has been reached. So !streamName.eof() checks β€œis there more to read?”
Listing 11.7.1.
You may notice one extra line of output. 60 is printed twice even though the file just has 10 20 30 40 50 60. Why is this?
The datafile has a newline character at the end of each line. It looks like this:
10 20 30(newline)
40 50 60(newline)
(eof)
So when we read the 60, the >> operator gets that token, sees the newline, and stops. We have not yet hit the end of file marker! So the loop does not stop. we then try to read in a 7th value, that fails, and so the variable keeps its existing value of 60.
Our code would work if the file looked like this:
10 20 30(newline)
40 50 60(eof)
In that case, after reading the 60 we would have reached the end of file marker.
To handle either case, we can just check for an error after reading in our data. Once we get past the 60, doing inFile >> number will fail if there is no more data to read. So if we have a failure, it might just mean we reached the end of the file. (Of course it could be some other issue. If we wanted to differentiate between the two we would have to check both inFile.eof() and inFile.fail()). This version uses that strategy:
Listing 11.7.2.

Insight 11.7.1.

It is a good idea to check for errors after attempting to read data anyway. So inFile.fail() is both handling a possible blank line at the end of the file and it will handle any other read errors (like trying to read "cat" as an integer).
There is a C++ idiom that can let us simplify our error checking. When we do inFile >> variable, it attempts to read the data and then evaluates to true if the read was successful, or false if it failed. So we can use that expression as the test in a loop:
Listing 11.7.3.
Each time we do the while’s test, we attempt to read in a value. If that works, the loop body executes. Once the input fails, the expression inFile >> variable evaluates to false, and the loop terminates. This structure is less flexible - it does not easily allow for handling errors that we want to try to recover from. But it does simplify the basic version of reading in from a file.

Checkpoint 11.7.1.

You have attempted of activities on this page.