转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://huahualala.blogbus.com/logs/10078056.html
3.1.1 Testing for end of input
Conceptually, the only really new part of this program is the condition in the while
statement. That condition implicitly uses an istream
as the subject of the while
condition:
while (cin >> x) {/*...*/}
The effect of this statement is to attempt to read from cin
. If the read succeeds, x
will hold the value that we just read, and the while
test also succeeds. If the read fails (either because we have run out of input or because we encountered input that was invalid for the type of x
), then the while
test fails, and we should not rely on the value of x
.
Understanding how this code works is a bit subtle. We can start by remembering that the >>
operator returns its left operand, so that asking for the value of cin >> x
is equivalent to executing cin >> x
and then asking for the value of cin
. For example, we can read a single value into x
, and test whether we were successful in doing so, by executing
if (cin >> x) {/*...*/}
This statement has the same meaning as
cin >> x; if (cin) { /* ... */ }
When we use cin >> x
as a condition, we aren't just testing the condition; we are also reading a value into x
as a side effect. Now, all we need to do is figure out what it means to use cin
as a condition in a while
statement.
Because cin
has type istream
, which is part of the standard library, we must look to the definition of istream
for the meaning of if (cin)
or while (cin)
. The details of that definition turn out to be complicated enough that we won't discuss it in detail until §12.5/222. However, even without these details, we can already understand a useful amount of what is happening.
The conditions that we used in Chapter 2 all involved relational operators that directly yield values of type bool
. In addition, we can use expressions that yield values of arithmetic type as conditions. When used in a condition, the arithmetic value is converted to a bool
: Nonzero values convert to true
; zero values convert to false
. For now, what we need to know is that similarly, the istream
class provides a conversion that can be used to convert cin
into a value that can be used in a condition. We don't yet know what type that value has, but we do know that the value can be converted to bool
. Accordingly, we know that the value can be used in a condition. The value that this conversion yields depends on the internal state of the istream
object, which will remember whether the last attempt to read worked. Thus, using cin
as a condition is equivalent to testing whether the last attempt to read from cin
was successful.
There are several ways in which trying to read from a stream can be unsuccessful:
- We might have reached the end of the input file.
- We might have encountered input that is incompatible with the type of the variable that we are trying to read, such as might happen if we try to read an
int
and find something that isn't a number. - The system might have detected a hardware failure on the input device.
In any of these cases, the effect is the same: Using this input stream as a condition will indicate that the condition is false. Moreover, once we have failed to read from a stream, all further attempts to read from that stream will fail until we reset the stream, which we'll learn how to do in §4.1.3/57.