Why is not in.good () the same as! In.fail ()?

I read that the following is an anti-pattern:

while(in.good()) { // ... } 

But this is preferable:

 while(operation) { } 

However, the thread has a conversion operator for bool, which returns !fail() . Does !fail() not match good() ? If not, then why are these two functions not symmetrical? I expect it to look like true == !false .

+5
source share
3 answers

There's a great table at http://en.cppreference.com/w/cpp/io/basic_ios/good that explains the status of std::istream and the values โ€‹โ€‹returned by various functions.

The only time while ( stream.good() ) and while(stream) will be different when the contents of the stream were successfully read and EOF reached. At this time, stream.good() returns true , and (bool)stream returns false.

+2
source

in.good() is true if the previous read operation was successful, but EOF does not occur. (It is possible that EOF occurs even if the read operation succeeds.) Therefore, if in.good() is false, or the previous read operation failed - in this case the next one will also fail - or the EOF was encountered - - in this case the next read operation will also fail. Therefore, if in.good() is false, the next read operation will definitely fail. If we want to know whether to do a read operation, we should test in.good() .

But the fact that in.good() true does not guarantee anything. Suppose in ends with a space, which usually happens because text files must end with a newline. Formatted read operations stop at the first space character, and unget back to the input stream, so if the previous read operation reads the last data item, it still does not leave the stream in EOF, and in will still be good . [Cm. Note 1]. Therefore, if your loop looks like this:

 while (in.good()) { in >> x; /* Do something with x assuming that it is valid */ } 

then you wonโ€™t notice when the last in >> x ends, and you end using the undefined x value in the last loop. (Probably the last value will be processed twice.)

The same thing happens if your loop was while (!in.bad()) or while (!in.eof()) .

Are you sure you want to check if in >> x succeeded. Nothing more. And the classic way to do this:

 while (in >> x) { /* If we get here, x has a legitimate value */ ... } 

in >> x just returns in , so it is exactly equivalent

 while (in >> x, in) { /* ... */ } 

In other words, bool(in) is false exactly when the previous operation failed, and true exactly when it succeeded. This is not the same as in.good() , because we still do not want to check if EOF has been encountered.

Notes:

  • As indicated in the first paragraph, reading can be successful, as well as installing EOF. One of the ways that this can happen is that the file does not end with a newline. This is pretty rare, but you shouldn't rule it out. And the fact that this can happen, which is why in.bad() does not check the eof flag: in.bad() is false, which means that the previous read operation failed.
+2
source

in.good () equals: [ios documentation]

 ! ( in.eof() || in.fail() || in.bad() ) 
0
source

Source: https://habr.com/ru/post/1232379/


All Articles