2

I know, there was hundreds questions about fail and eof, but no one was able to answered my question. In this example, only eof bit will be set:

while (!Ifstream.eof()){
    Ifstream >> Buffer;
    cout << Buffer << endl;
}

But in this example, eof bit as well as fail bit will be set:

 while (!Ifstream.fail()){
    Ifstream >> Buffer;
    cout << Buffer << endl;
}

What is the reason of this two differences? .I consider only situation, when stream reach end of file.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
user3609885
  • 66
  • 1
  • 8
  • This Q&A has some information what's actually going on: [Why is iostream::eof inside a loop condition considered wrong?](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) – πάντα ῥεῖ Jan 10 '15 at 12:38
  • 1
    The codes in the loops are identical. I don´t believe you that the same code will set different bits. – deviantfan Jan 10 '15 at 12:38
  • @deviantfan: I think `Ifstream` is an input stream. It's about the condition in the `while` loop I think. – Willem Van Onsem Jan 10 '15 at 12:42
  • @CommuSoft Yes, of course (?) – deviantfan Jan 10 '15 at 12:44
  • 1
    This is possible. Your formatted input could read until the end of the stream, where the last extraction is successful, and set the EOF bit. Then the first loop would stop. The second loop wouldn't, and would try to extract again, setting the fail bit too. – Joseph Mansfield Jan 10 '15 at 12:45
  • 1
    @deviantfan: well the question is what the difference is between the two conditions I think, so it can set different content. Indeed the bit's wont differ, but the "number of" can. – Willem Van Onsem Jan 10 '15 at 12:45
  • @JosephMansfield Didn´t thought about that :p – deviantfan Jan 10 '15 at 12:46

3 Answers3

5

The difference is very slight.

The first piece of code, tries reading as long as it doesn't hit EOF condition. Then it breaks. But, if for some reason an error occurrs (i.e. failure to convert data through << operator), this piece of code will loop indefinitely, since FAIL will be set on error, reading will stop, and EOF will never be hit.

The second piece of code works with a small trick. It reads as long as it can and stops when error occurs. Ok, logical. However, when hittin an end-of-file, but IIRC the EOF condition will not be set yet. So, the loop will run once more, try to read at EOF state, and that will rise the FAIL flag and break the loop. But that also means that you will get one processing ( cout<

The right way to do is to check immediatelly whether READING succeeded:

while (true){
    if(!(Ifstream >> Buffer))
         break;
    cout << Buffer << endl;
}

only that will guarantee you that the loop will stop as soon as read fails, be it EOF or FAIL or other cause.

As MatsPetersson and πάντα ῥεῖ have suggested, the above snippet may be "squashed" to form:

while (Ifstream >> Buffer)
    cout << Buffer << endl;

and that's the usual way to write it. No fail/good/eof checks needed. The value returned from operator>> is the stream itself (like in operator<<) and stream is testable for "truthness", so it's just as simple as that. When talking about fail/good/eof differences, I like to write the longer form to emphasize that .. you shouldn't use fail/good/eof in the while-condition at all, and that you should check the state of the stream only after actually trying to read from it. while(true) shows the point very clearly.

quetzalcoatl
  • 32,194
  • 8
  • 68
  • 107
  • 1
    Why not simply `while (Ifstream >> Buffer)`? – πάντα ῥεῖ Jan 10 '15 at 12:52
  • To clarify, hitting the end of file doesn't necessarily set the fail bit (in particular, when the EOF delimits what you're extracting). – Joseph Mansfield Jan 10 '15 at 12:57
  • @quetzalcoatl I think the best way to describe this is that "attempting to read something but failing to do so will set the fail bit". It just so happens that that will happen when you're at the end of the file and attempt to read something. Another example is if you do `s >> an_int` and there is only whitespace between the current position and the end of the file, or perhaps if there's some non-numeric characters. Since it can't read the `int`, it fails. – Joseph Mansfield Jan 10 '15 at 13:01
4

fail is different from eof in that it covers various other error conditions than "file reached its end".

For example, if Buffer is int Buffer then the second will stop on reading ABC, where the first one will loop forever (not making any progress, as ABC is not numeric input).

Of course, the CORRECT thing to do is:

while(Ifstream >> Buffer) 
{
   cout << Buffer << endl;
}

that will stop both on EOF and invalid input (if applicable), as well as not performing the cout << Buffer << endl; when the fail or eof condition happens.

[Note that the while(!eof()) solution is valid in for example Pascal, because in Pascal, the input is "pre-read", so that the current read knows if "the next read will result in EOF" before you actually TRY to read it. C and C++ doesn't mark EOF until you actually READ past the end of the file.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
1

Programically, 'EOF in read' and 'fail of read' is described differently.

EOF indicates End Of File. So, programmer knows when they have to stop reading file.

But 'fail' is indicates 'not successfully' It means some process ends with wrong state or exception has been occurred when execute the process.