PRODUCT : Borland C++ NUMBER : 1385 VERSION : ALL OS : ALL DATE : October 25, 1993 PAGE : 1/3 TITLE : Streams: Part 3 -- Error Checking Streams : Part 3 : Error Checking Generally the most neglected part of programming in C++ is error checking. This is a result of needing an extra step to check operations. Streams are no exception to this rule. The difficulty is we do not get a return type indicating an error when using the provided syntax. As we saw in part 2, the return type is a reference to a stream object. This return type allows us to have concatenated stream statements like: cout << "The value is " << 5 << endl; The question then is how do we check for errors? The answer is simple. Following the stream statement we need to check for an error. Error states are maintained in the ios class in an integer variable named "state". State will hold one or more of the following values: goodbit = 0x00, // no bit set: all is ok eofbit = 0x01, // at end of file failbit = 0x02, // last I/O operation failed badbit = 0x04, // invalid operation attempted hardfail = 0x80 // unrecoverable error Overlaoding once again increases the ease of using streams. When checking for errors we use the ! operator and the void * operator. The following are the prototypes of the overloaded operators: _Cdecl operator void _FAR * (); // zero if state failed int _Cdecl operator! (); // non-zero if state failed Here is an example of checking for errors: cout << "The value is " << 5 << endl; if (!cout) Error(); In this example we see that the ! (not) operator is used to indicate if the stream is no longer in a good state. If an error had occurred the function Error() would have been called. You PRODUCT : Borland C++ NUMBER : 1385 VERSION : ALL OS : ALL DATE : October 25, 1993 PAGE : 2/3 TITLE : Streams: Part 3 -- Error Checking could also take the approach of continuing while there isn't an error, as in the following example: if (cout) cout << "The value is " << 5 << endl; if (cout) cout << "The next value is " << 10 << endl; This example illustrates that the cout object will return true as long as the error state of the object is clear. The use of cout alone maps to the overloaded operator void *. The beauty of the previous example becomes clear when we look at the following example: while (MyStreamFile) { MyStreamFile << "Next Value"; } Both the operation and error checking are performed. Lastly, you may also call one of the following functions provided for error checking directly: int _Cdecl rdstate(); // return the stream state int _Cdecl eof(); // non-zero on end of file int _Cdecl fail(); // non-zero if an operation failed int _Cdecl bad(); // non-zero if error occurred int _Cdecl good(); // non-zero if no state bits set Examples of using the previous functions follow: if (stream.bad()) { // Perform error recovery. } if (stream.good()) { // Continue I/O. } PRODUCT : Borland C++ NUMBER : 1385 VERSION : ALL OS : ALL DATE : October 25, 1993 PAGE : 3/3 TITLE : Streams: Part 3 -- Error Checking if (stream.eof()) { // We have reached the end of file. } If we used the non-direct functions, i.e. using cout or !cout in an if() statement, then we we know when an error occurred, but not what the error was. Since the error state is maintained until explicitly cleared we can use the specific provided functions i.e. eof(), for error identification. ONCE AN ERROR HAS OCCURRED ALL OPERATIONS FOLLOWING THAT POINT WILL CONTINUE TO FAIL. To clear the an error state in a stream object we use the function clear. The clear functions prototype is as follows: void _Cdecl clear(int = 0); // set the stream state The function has a default argument of 0, therefore calling the function without passing a parameter will set the state variable to 0 (also called the goodbit). Part 3 covered the concepts of error checking. For more information on streams please see the following list: Part 1 : Introduction Part 2 : Built-in Types and Manipulators Part 3 : Error Checking Part 4 : User Classes Part 5 : File Input and Output Part 6 : In-Memory Formatting Part 7 : Printing DISCLAIMER: You have the right to use this technical information subject to the terms of the No-Nonsense License Statement that you received with the Borland product to which this information pertains.