13.8 Stream Error States

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.

Fig. 13.20 Testing error states.

Alternate View

 1   // Fig. 13.20: Fig13_20.cpp
 2   // Testing error states.
 3   #include <iostream>
 4   using namespace std;
 5
 6   int main() {
 7      int integerValue;
 8
 9      // display results of cin functions
10      cout << "Before a bad input operation:"
11         << "
cin.rdstate(): " << cin.rdstate()
12         << "
    cin.eof(): " << cin.eof()    
13         << "
   cin.fail(): " << cin.fail()   
14         << "
    cin.bad(): " << cin.bad()    
15         << "
   cin.good(): " << cin.good()   
16         << "

Expects an integer, but enter a character: ";
17
18      cin >> integerValue; // enter character value
19
20      // display results of cin functions after bad input
21      cout << "
After a bad input operation:"
22         << "
cin.rdstate(): " << cin.rdstate()
23         << "
    cin.eof(): " << cin.eof()    
24         << "
   cin.fail(): " << cin.fail()   
25         << "
    cin.bad(): " << cin.bad()    
26         << "
   cin.good(): " << cin.good();
27
28      cin.clear(); // clear stream
29
30      // display results of cin functions after clearing cin
31      cout << "

After cin.clear()" << "
cin.fail(): " << cin.fail()
32         << "
cin.good(): " << cin.good() << endl;
33   }

Before a bad input operation:
cin.rdstate(): 0
    cin.eof(): 0
   cin.fail(): 0
    cin.bad(): 0
   cin.good(): 1

Expects an integer, but enter a character: A

After a bad input operation:
cin.rdstate(): 2
    cin.eof(): 0
   cin.fail(): 1
    cin.bad(): 0
   cin.good(): 0

After cin.clear()
cin.fail(): 0
cin.good(): 1

Member Function 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.

Member Function 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.

Member Function 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.

Member Function 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.

Member Function 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.

Causing an Error in the Input Stream and Redisplaying the Stream’s State

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).

Clearing the Error State So You May Continue Using the Stream

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.

Overloaded Operators ! 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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset