Let’s take a closer look at what happens for inappropriate input. A cin or cout object contains a data member (inherited from the ios_base class) that describes the
Table 17.4. Stream States
Setting States
Two of the methods in Table 17.4, clear() and setstate(), are similar. Both reset the state, but they do so in a different fashion. The clear() method sets the state to its argument. Thus, the following call uses the default argument of 0, which clears all three state bits (eofbit, badbit, and failbit):
clear();
Similarly, the following call makes the state equal to eofbit; that is, eofbit is set, and the other two state bits are cleared:
clear(eofbit);
The setstate() method, however, affects only those bits that are set in its argument. Thus, the following call sets eofbit without affecting the other bits:
setstate(eofbit);
So if failbit was already set, it stays set.
Why would you reset the stream state? For a program writer, the most common reason is to use clear() with no argument to reopen input after encountering mismatched input or end-of-file; whether doing so makes sense depends on what the program is trying to accomplish. You’ll see some examples shortly. The main purpose for setstate() is to provide a means for input and output functions to change the state. For example, if num is an int, the following call can result in operator>>(int &) using setstate() to set failbit or eofbit:
cin >> num; // read an int
I/O and Exceptions
Suppose that an input function sets eofbit. Does this cause an exception to be thrown? By default, the answer is no. However, you can use the exceptions() method to control how exceptions are handled.
First, here’s some background. The exceptions() method returns a bitfield with three bits corresponding to eofbit, failbit, and badbit. Changing the stream state involves either clear() or setstate(), which uses clear(). After changing the stream state, the clear() method compares the current stream state to the value returned by exceptions(). If a bit is set in the return value and the corresponding bit is set in the current state, clear() throws an ios_base::failure exception. This would happen, for example, if both values had badbit set. It follows that if exceptions() returns goodbit, no exceptions are thrown. The ios_base::failure exception class derives from the std::exception class and thus has a what() method.
The default setting for exceptions() is goodbit—that is, no exceptions thrown. However, the overloaded exceptions(iostate) function gives you control over the behavior:
cin.exceptions(badbit); // setting badbit causes exception to be thrown
The bitwise OR operator (|), as discussed in Appendix E, allows you to specify more than one bit. For example, the following statement results in an exception being thrown if either badbit or eofbit is subsequently set:
cin.exceptions(badbit | eofbit);
Listing 17.12 modifies Listing 17.11 so that the program throws and catches an exception if failbit is set.
Listing 17.12. cinexcp.cpp
// cinexcp.cpp -- having cin throw an exception
#include
#include
int main()
{
using namespace std;
// have failbit cause an exception to be thrown
cin.exceptions(ios_base::failbit);
cout << "Enter numbers: ";
int sum = 0;
int input;
try {
while (cin >> input)
{
sum += input;
}
} catch(ios_base::failure & bf)
{
cout << bf.what() << endl;
cout << "O! the horror!\n";
}
cout << "Last value entered = " << input << endl;
cout << "Sum = " << sum << endl;
return 0;
}
Here is a sample run of the program in Listing 17.12; the what() message depends on the implementation:
Enter numbers: 20 30 40 pi 6
ios_base failure in clear
O! the horror!
Last value entered = 40.00
Sum = 90.00