### Correcting Input Stream Errors

When an input statement is requesting input of one type, and erroneous input or input of another type is provided, the error state of the input stream is set to ios::badbit and ios::failbit, and further input operations may not work properly. For example, the following code repeatedly displays the text: Enter an integer value: if the first input provided is a string whose initial characters do not form an integer value:

    #include <iostream.h>
    void main() {
       int i=-1;
       while (i<=0) {
          cout << "Enter a positive integer: " ;
          cin >> i;
          }
       cout << "The value was " << i << endl;
    }

This program loops indefinitely, given an input such as ABC12, because the erroneous input causes the error state to be set in the stream, but does not clear the error state or advance the get pointer in the stream beyond the erroneous characters. Each time the input operator is called for an int (as in the while loop above), the same characters are read in.

To clear an input stream and repeat an attempt at input you must add code to do the following:

1. Clear the stream's error state.
2. Remove the erroneous characters from the stream.
3. Attempt the input again.

You can determine whether the stream's error state has been set in one of the following ways:

- By calling fail() for the stream (shown in the example below)
- By calling bad(), oef(), good(), or rdstate().
- By using the void* type conversion operator (for example, if (cin)).
- By using the operator! operator (shown in the comment in the example below)

You can clear the error state by calling clear(), and you can remove the erroneous characters using ignore(). The example above could be improved, using these suggestions, as follows:

    #include <iostream.h>

    void main() {
       int i=-1;
       while (i==-1) {
          cout << "Enter an integer value: ";
          cin >> i;
          while (cin.fail()) {   // could also be "while (!cin) {"
             cin.clear();
             cin.ignore(1000,'\n');
             cerr << "Please try again: ";
             cin >> i;
            }
          }
       cout << "The value was " << i << endl;
    }

The ignore() member function with the arguments shown above removes characters from the input stream until the total number of characters removed equals 1000, or until the new-line character is encountered, or until EOF is reached. This example produces the output shown below in regular type, given the input shown in bold:

    Enter an integer value:
    ABC12
    Please try again:
    12ABC
    The value was 12

Note that, for the second attempt at input, the error state is set after the input of 12, so the call to cin.fail() after the corrected input returns false. If another integer input were requested after the while loop ends, the error state would be set and that input would fail.

When you define an input operator of class type, you can build error-checking code into your definition. If you do so, you do not have to check for error-causing input every time you use the input operator for objects of your class type. Consider the class definition for the PhoneNumber data type shown in myclass.h, and the following input operator definition:

    istream& operator>> (istream& aStream, PhoneNumber& aPhoneNum) {
       int AreaCode, Exchange, Local;
       aStream >> AreaCode;
         while (aStream.fail()) eatNonInts(aStream,AreaCode);
       aStream >> Exchange;
         while (aStream.fail()) eatNonInts(aStream,Exchange);
       aStream >> Local;
         while (aStream.fail()) eatNonInts(aStream,Local);
       aPhoneNum=PhoneNumber(AreaCode, Exchange, Local);
       return aStream;
       }

The eatNonInts() function in this example should be defined to ignore all characters in the input stream until the next integer character is encountered, and then to read the next integer value into the variable provided as its second argument. The function could be defined as follows:

    void eatNonInts(istream& aStream, int& anInt) {
       char someChar;
       aStream.clear();
       while (someChar=aStream.peek(), !isdigit(someChar))
          aStream.get(someChar);
       aStream >> anInt;
       }

Now whenever input is requested for a PhoneNumber object and the provided input contains nonnumeric data, this data is skipped over. Note that this is only a primitive error-handling mechanism; if the input provided is 416 555 2p45 instead of 416 555 2045, the characters p45 will be ignored and the local is set to 2 rather than 2045. A more complete example would check each input for the correct number of digits.