the content of the file "zhouting.txt" is "zhouting like lichao!" |
I tested the program with exactly that file content. This was the output:
zhouting
like
lichao!
istream accessable |
but ... if I press enter at the end of the line, the file content becomes
"zhouting like lichao!\n" |
and the output is now:
zhouting
like
lichao!
lichao!
istream accessable |
That is only part of the problem. The behaviour is inconsistent depending on presence of whitespace. When the last item is read, because there is whitespace afterwards, end of file is not reached. But on the next iteration, the read will fail, so it just prints out the existing contents of the variable
str
.
The other part of the problem is we don't even know whether the file is being read at all.
Let's change the code to this, but keep the same input file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
#include <fstream>
#include <iostream>
using namespace std;
istream &iostream_input(istream &is)
{
// string str;
int str = 0; // use an integer instead of a string
while (!is.eof())
{
is >> str;
cout << str << endl;
}
is.clear();
if (!is.rdstate())
cout<<"istream accessable"<<endl;
else
cout<<"istream forbiden"<<endl;
return is;
}
int main()
{
ifstream str("./zhouting.txt");
iostream_input(str);
}
|
The output is now
0
0
0
0
0
0
0
0
0
0
0
0
... repeat to infinity |
The solution to both problems is the same.
Check that the file was actually read before trying to proceed.
eof()
at the start of the loop tells you about what happened
in the past. It does not predict whether or not the
next read attempt will be successful. In addition not all conditions will even set eof() at all. If there is an error,
eof
will
never be true and it will loop forever.
The easiest way to do that is to put the input operation inside the loop condition (and forget you ever heard of eof()
* ... at least for now).
Change this:
to this:
*There are valid uses for eof() but they may be considered advanced /specialised applications.