On 06-Mar-17 10:05 PM, Christiano wrote:
> First, on my computer the bits FAIL, EOF, BAD (Composing the istream
> state) are organized as follows:
> Table 1:
> fail eof bad state
> 0 0 0 0 (good state)
> 0 0 1 1
> 0 1 0 2
> 0 1 1 3
> 1 0 0 4
> 1 0 1 5
> 1 1 0 6
> 1 1 1 7
>
> Page 355 of PPP2[1]
Uhm, remember to align things for monospaced font.
Anyway, you don't need and should not consider how the bits are placed.
Just use the symbolic names. E.g.,
if( cin.rdstate() & ios_base::eofbit ) {
cout << "stream state has eofbit set" << endl;
}
if( cin.rdstate() & ios_base::badbit ) {
cout << "stream state has badbit set" << endl;
}
if( cin.rdstate() & ios_base::failbit ) {
cout << "stream state has failbit set" << endl;
}
> ### Statement 1 ###:
> "A stream that is bad() is also fail()"
>
> This statement seems to work in the vast majority of cases, but it can't
> be postulated as a general rule.
It /should/ work in all cases, otherwise the stream implementation is buggy.
> See the example:
>
> #include <iostream>
>
> int main()
> {
> std::cin.ignore(10000, 'q');
> std::cout << std::cin.rdstate() << std::endl;
>
> return 0;
> }
>
> using this input (linux environment):
> adsadasasas <ENTER>
> <CTRL+D>
>
> Result: 2
> Reading table 1 we have:
> fail eof bad
> 0 1 0
>
> That is: In the same way as we have an example where eof appears alone
> without fail, we could have bad alone without fail.
No, they're different things.
`bad` is really, really bad.
E.g., that you're reading a file from a corrupted storage device.
> This happens because when using "ignore" we are not reading for a
> variable and therefore would not justify a fail since this only happens
> when we have a formatted problem (That can only occur when we are
> reading for a variable.).
Right. EOF is not always `fail`. It can be detected by `ignore`, not
just by a failing read.
> I've used the example with eof because it's hard to create examples with
> bad.
The reason it's hard is because it would have to demonstrate a bug in
the implementation.
> Then the book says:
> ### Statement 2 ###:
> "The !cin can be read as 'cin is not good' or 'Something went wrong with
> cin' or 'the state of cin is not good()'."
>
> But this is not true, !cin means "cin is fail", as said by standard:
> ISO/IEC 14882:2011(E) [2],
27.5.5.4:
> ------------------------------------------
> explicit operator bool() const;
> Returns: !fail()
>
> bool operator!() const;
> Returns: fail()
> ------------------------------------------
The statement is true and the standard is by definition correct.
I.e. this means that you need to adjust your interpretation of the
statement. It clearly does not refer to /technical/ good(), because
`good()`, testing for all zero, is not the exact opposite of `fail()`,
which tests for `badbit` or `failbit` set. I.e. you can have `eofbit`
and still be `good()`, technically, but not in the everyday language
sense that Bjarne uses in that explanation for beginners.
However, I think a better explanation than Bjarne's is just that
`fail()` tells you that some operation failed.
Your discovery here is that you can have EOF detected without an
operation having failed. That's a good discovery.
A possible explanation of `good()`, which is not the opposite of
`fail()`, is that it tells that you that no potential problem at all has
been detected, not even EOF.
> Example:
> #include <iostream>
>
> int main()
> {
> std::cin.ignore(10000, 'q');
>
> if(!std::cin)
> std::cout << "Test 1: first" << std::endl;
> else
> std::cout << "Test 1: second" << std::endl;
>
> std::cout << std::cin.rdstate() << std::endl;
>
>
> return 0;
> }
>
> input (linux environment)
> asdasdasdasd <ENTER>
> <ctrl+D>
>
> Result:
> Test 1: second
> 2
>
> If statement 2 were true, then the result should be:
> Test 1: first
> 2
No no. :)
>
> ---------------------------------------------------------------
> [1]
http://stroustrup.com/Programming/
> ISBN 978-0-321-99278-9
> Programming: Principles and Practice using C++ (Second Edition)
> In respect to the group and author:
> I have the original book,
> Using here only a little portion of the book for
> educational/research purposes according to fair use.
>
> [2] ISO/IEC 14882:2011
> I have the original standard,
> Using here only a little portion for
> educational/research purposes according to fair use.
Bjarne is a good author in the sense that he keeps public errata lists.
If this specific possible problem had turned out to be a real one, you
could have reported it to him and he would have corrected for a later
edition, and included it in errata list.
However, there are some problems with the book that are not the kind
that would end up as errata, in particular Bjarne's use of a macro in
his general standard library header. I don't recall the details. But
such problems can halt the progress of a novice following the book.
Just remember that nothing and nobody is perfect. There are always
problems. ;-)
The iostreams design, its evolution after Bjarne's original simple
thing, is IMHO a very clear example of overwhelming imperfectness.
Cheers!,
- Alf