Each stream object contains a set of state bits that represent a stream’s state—sticky format settings, error indicators, etc. Earlier in the book, we indicated that you can test, for example, whether an input was successful. You can test this through bits of class ios_base
—the base class of the stream classes. Stream extraction sets the stream’s failbit
to true if the wrong type of data is input. Similarly, stream extraction sets the stream’s badbit
to true if the operation fails in an unrecoverable manner—for example, if a disk fails when a program is reading a file from that disk. Figure 13.20 shows how to use bits like failbit and badbit to determine a stream’s state.2 In industrial-strength code, you’ll want to perform similar tests on every I/O operation. Chapter 22 discusses bits and bit manipulation in detail.
eof
The program begins by displaying the stream’s state before receiving any input from the user (lines 10–15). Line 12 uses member function eof
to determine whether end-of-file has been encountered on the stream. In this case, the function returns 0 (false). The function checks the value of the stream’s eofbit
data member, which is set to true for an input stream after end-of-file is encountered after an attempt to extract data beyond the end of the stream.
fail
Line 13 uses the fail
member function to determine whether a stream operation has failed. The function checks the value of the stream’s failbit
data member, which is set to true, for example, on an a stream when a format error occurs and as a result no characters are input (e.g., when you attempt to read a number and the user enters a string). In this case, the function returns 0 (false). When such an error occurs on input, the characters are not lost. Usually, recovering from such input errors is possible.
bad
Line 14 uses the bad
member function to determine whether a stream operation failed. The function checks the value of the stream’s badbit
data member, which is set to true for a stream when an error occurs that results in the loss of data—such as reading from a file when the disk on which the file is stored fails. In this case, the function returns 0 (false). Generally, such serious failures are nonrecoverable.
good
Line 15 uses the good
member function, which returns true
if the bad
, fail
and eof
functions would all return false
. The function checks the stream’s goodbit
, which is set to true for a stream if none of the bits eofbit
, failbit
or badbit
is set to true for the stream. In this case, the function returns 1 (true). I/O operations should be performed only on “good” streams.
rdstate
The rdstate
member function (line 11) returns the stream’s overall error state. The function’s return value could be tested, for example, by a switch
statement that examines eofbit
, badbit
, failbit
and goodbit
. The preferred means of testing the state of a stream is to use member functions eof
, bad
, fail
and good
—using these functions does not require you to be familiar with particular status bits.
Line 18 reads a value into an int
variable. You should enter a string rather than an int
to force an error to occur in the input stream. At this point, the input fails and lines 21–26 once again call the streams’s state functions. In this case, fail
returns 1 (true), because the input failed. Function rdstate
also returns a nonzero value (true), because at least one of the member functions eof
, bad
and fail
returned true. Once an error occurs in the stream, function good
returns 0 (false).
After an error occurs, you can no longer use the stream until you reset its error state. The clear
member function (line 28) is used to restore a stream’s state to “good,” so that I/O may proceed on that stream. Lines 31–32 then show that fail returns 0 (false) and good returns 1 (true), so the input stream can be used again.
The default argument for clear
is goodbit
, so the statement
cin.clear();
clears cin
and sets goodbit
for the stream. The statement
cin.clear(ios::failbit)
sets the failbit
. You might want to do this when performing input on cin
with a user-defined type and encountering a problem. The name clear
might seem inappropriate in this context, but it’s correct.
!
and bool
Overloaded operators can be used to test a stream’s state in conditions. The operator!
member function—inherited into the stream classes from class basic_ios
—returns true
if the badbit
, the failbit
or both are true. The operator bool
member function (added in C++11) returns false
if the badbit
is true, the failbit
is true or both are true. These functions are useful in I/O processing when a true
/false
condition is being tested under the control of a selection statement or iteration statement. For example, you could use an if
statement of the form
if (!cin) {
// process invalid input stream
}
to execute code if cin
’s stream is invalid due to a failed input. Similarly, you’ve already seen a while
condition of the form
while (cin >> variableName) {
// process valid input
}
which enables the loop to execute as long as each input operation is successful and terminates the loop if an input fails or the end-of-file indicator is encountered.