void ReadTheData(ifstream& in_stream, ofstream& out_stream)
{
using namespace std;
int id;
char name[100] = "";
double balance;
in_stream >> id >> name >> balance;
while(name[0] || ! in_stream.eof()) // Continue looping until eof or name is not present.
{
cout << id << '\t' << name << '\t' << balance << endl;
in_stream >> id >> name >> balance;
}
}
the Balance.txt has format style:
4248749 Kelly_E 460.02
8898693 Kelly_George_MD 1764.68
4597789 Lambert_Richard 1571.79
When I run the code, the last line in file Balance.txt goes into an infinite loop, how do I stop the infinite loop?
Somehow this question manages to get asked about 100 different ways, none of which is quite a duplicate of the others. Worse, every time it gets asked, it gets a ridiculous number of bad answers.
To read the data correctly from a stream, you want a loop with a single condition that reads the data and checks whether that attempt at reading succeeded. Almost anything else is prone to failure. In particular, it's nearly impossible to get a loop of the form:
while (!foo.eof())
or:
while (!foo.bad())
or:
while (foo.good())
or:
while (file)
...to actually work correctly. Every one of these is fundamentally broken. The easy way to get correct results is to combine reading and testing into a single operation, such as:
while (std::getline(somefile, somestring))
or:
while (file >> a >> b >> c)
As to why these work and the others don't: end of file is not detected immediately upon the file pointer reaching the end of the file. Rather, it's detected when you attempt to read something, but the file pointer is already at the end of the file.
So, what happens is that when at the point that you've read all the data in the file, file.eof()
remains false. You attempt to read the next item from the file (and it fails). Then you attempt to process the data even though the read failed.
The reason the forms I recommend work correctly is that they attempt to read data, then check whether that succeeded, and immediately exit the loop if the attempted read failed, so they do not attempt to process data after a read attempt failed.
As a sort-of separate (but closely related) point: if you're trying to read an entire file, you do not normally want to base exiting the loop specifically on detecting end of file. You want to read as long as you can convert input, and exit the loop as soon as that fails.
These are different when/if you encounter some other error before reaching the end of the file. In such a case, a loop that waits specifically for end of file can (and often will) continue running indefinitely, repeatedly attempting an operation that has already failed, but failed in a way that the loop isn't written to detect correctly.
The time to use file.eof()
is after you've exited from the loop, and want to detect why the loop exited. If you've reached eof, great--you just read all the data. If you expected the loop to read the entire file, but it exited before reaching eof, then you probably have a problem -- perhaps a problem with the disk drive, or perhaps just bad data in the file. You can typically use file.eof
, file.fail
and file.bad
to sort out what sort of error you encountered (if any).
When you try to read using
in_stream >> id >> name >> balance;
after the last line has been read, the failbit
as well as the eofbit
are most likely set. You can use istream::good()
to detect whether the istream
is still in a valid state.
Change the line
while(name[0] || ! in_stream.eof())
to
while(in_stream.good())
or
while(in_stream)