TITLE: fail() and bad() for input streams (Newsgroups: comp.lang.c++.moderated) RANDLE: "Chris P. Randle" >First off, I did my homework and searched Marshall Cline's FAQ like >a good comp.lang.c++'ER and found this: > >=== Presented here for convinence >[13.3] Why does my input seem to process past the end of file? > >Because the eof state is not set until after a read is attempted past >the end of file. That is, reading >the last byte from a file does not set the eof state. > >For example, the following code has an off-by-one error with the count >i: > > int i = 0; > while (! cin.eof()) { // WRONG! > cin >> x; > ++i; > // Work with x ... > } > >What you really need is: > > int i = 0; > while (cin >> x) { // RIGHT! > ++i; > // Work with x ... > } CLAMAGE: clamage@Eng.Sun.COM (Steve Clamage), 29 Jun 96 Marshall is essentially correct. Reading the last byte of a file might not set the eof bit, but it might. EOF is not predictive. How do you tell if you have read the last character to be typed from a keyboard or to be read from a pipe? The only way to tell is to try to read more and fail. For disk files, the file system might report EOF simultaneously with presenting the last character. In that case, the EOF indication might be premature. (You hit EOF, but you did read data.) RANDLE: >==== >And I reread Stanley Lippmans book states this: >=== pg 559 C++ Primer >while (cin >> buf) evaluates to "0" on encountering EOF because of a >stream member conversion operator which is generally equivalent to the >following compound expression: > if (! (cin.bad() || cin.fail())) //predefined logical NOT CLAMAGE: Stan missed the point that if "bad" is set, "fail" must also be set. It is enough just to test "fail". RANDLE: >My questions are: > >1) Does this mean that the expression: > while(someStream) > is really: > while (!(someStream.bad() || (someStream.fail())) CLAMAGE: Yes, or more simply: while( SomeStream ) is supposed have the same result as while( ! SomeStream.fail() ) RANDLE: >2) Are these tests the same (both will indicate a read past EOF)?: > someStream.fail() > someStream.eof() CLAMAGE: No. The "fail" and "eof" tests are not equivalent. "eof" is true if EOF has been reached, where the definition of "reached" is a bit slippery. "fail" means the last attempted operation did not succeed, for whatever reason. The two functions can return the same or opposite states. Example: If you attempt to read an integer, but the next available input characters are "abc", the operation fails, but eof is false. But if the file contained just "123" with no trailing whitespace, the operation succeeds, but you have also reached eof. You should find "fail" is false and "eof" is true. If you then attempt an additional input operation, it will fail (no more characxters to read) and "eof" will still be true. You can test "eof" before trying an operation. If it returns "true", you have reached eof and no characters will be read. If "eof" is false before attempting an input operation, the operation might succeed and might fail; there might or might not actually be any characters left. I would not test "eof" just after an input operation, since whether it is true or false, the input might or might not have succeeded, as in the examples above. Usually the best strategy is to attempt an input operation, then see whether it succeeded. Marshall Cline's example does exactly that.