Stream Input
Now let us consider stream input. Formatted and unformatted input capabilities are provided by istream. The stream extraction operator (i.e., the overloaded >> operator) normally skips white-space characters (such as blanks, tabs and newlines) in the input stream; later we will see how to change this behavior. After each input, the stream extraction operator returns a reference to the stream object that received the extraction message (e.g., cin in the expression cin >> grade). If that reference is used as a condition (e.g., in a while statement's loop-continuation condition), the stream's overloaded void * cast operator function is implicitly invoked to convert the reference into a non-null pointer value or the null pointer based on the success or failure of the last input operation. A non-null pointer converts to the bool value TRue to indicate success and the null pointer converts to the bool value false to indicate failure. When an attempt is made to read past the end of a stream, the stream's overloaded void * cast operator returns the null pointer to indicate end-of-file.
Each stream object contains a set of state bits used to control the state of the stream (i.e., formatting, setting error states, etc.). These bits are used by the stream's overloaded void * cast operator to determine whether to return a non-null pointer or the null pointer. Stream extraction causes the stream's failbit to be set if data of the wrong type is input and causes the stream's badbit to be set if the operation fails. Section 15.7 and Section 15.8 discuss stream state bits in detail, then show how to test these bits after an I/O operation.
15.4.1. get and getline Member Functions
The get member function with no arguments inputs one character from the designated stream (including white-space characters and other non-graphic characters, such as the key sequence that represents end-of-file) and returns it as the value of the function call. This version of get returns EOF when end-of-file is encountered on the stream.
Using Member Functions eof, get and put
Figure 15.4 demonstrates the use of member functions eof and get on input stream cin and member function put on output stream cout. The program first prints the value of cin.eof()i.e., false (0 on the output)to show that end-of-file has not occurred on cin. The user enters a line of text and presses Enter followed by end-of-file (-z on Microsoft Windows systems, -d on UNIX and Macintosh systems). Line 17 reads each character, which line 18 outputs to cout using member function put. When end-of-file is encountered, the while statement ends, and line 22 displays the value of cin.eof(), which is now TRue (1 on the output), to show that end-of-file has been set on cin. Note that this program uses the version of istream member function get that takes no arguments and returns the character being input (line 17). Function eof returns true only after the program attempts to read past the last character in the stream.
Figure 15.4. get, put and eof member functions.
(This item is displayed on pages 777 - 778 in the print version)
1 // Fig. 15.4: Fig15_04.cpp 2 // Using member functions get, put and eof. 3 #include 4 using std::cin; 5 using std::cout; 6 using std::endl; 7 8 int main() 9 { 10 int character; // use int, because char cannot represent EOF 11 12 // prompt user to enter line of text 13 cout << "Before input, cin.eof() is " << cin.eof() << endl 14 << "Enter a sentence followed by end-of-file:" << endl; 15 16 // use get to read each character; use put to display it 17 while ( ( character = cin.get() ) != EOF ) 18 cout.put( character ); 19 20 // display end-of-file character 21 cout << " EOF in this system is: " << character << endl; 22 cout << "After input of EOF, cin.eof() is " << cin.eof() << endl; 23 return 0; 24 } // end main
|
The get member function with a character-reference argument inputs the next character from the input stream (even if this is a white-space character) and stores it in the character argument. This version of get returns a reference to the istream object for which the get member function is being invoked.
A third version of get takes three argumentsa character array, a size limit and a delimiter (with default value ' '). This version reads characters from the input stream. It either reads one fewer than the specified maximum number of characters and terminates or terminates as soon as the delimiter is read. A null character is inserted to terminate the input string in the character array used as a buffer by the program. The delimiter is not placed in the character array but does remain in the input stream (the delimiter will be the next character read). Thus, the result of a second consecutive get is an empty line, unless the delimiter character is removed from the input stream (possibly with cin.ignore()).
Comparing cin and cin.get
Figure 15.5 compares input using stream extraction with cin (which reads characters until a white-space character is encountered) and input using cin.get. Note that the call to cin.get (line 24) does not specify a delimiter, so the default ' ' character is used.
Figure 15.5. Input of a string using cin with stream extraction contrasted with input using cin.get.
(This item is displayed on pages 778 - 779 in the print version)
1 // Fig. 15.5: Fig15_05.cpp 2 // Contrasting input of a string via cin and cin.get. 3 #include 4 using std::cin; 5 using std::cout; 6 using std::endl; 7 8 int main() 9 { 10 // create two char arrays, each with 80 elements 11 const int SIZE = 80; 12 char buffer1[ SIZE ]; 13 char buffer2[ SIZE ]; 14 15 // use cin to input characters into buffer1 16 cout << "Enter a sentence:" << endl; 17 cin >> buffer1; 18 19 // display buffer1 contents 20 cout << " The string read with cin was:" << endl 21 << buffer1 << endl << endl; 22 23 // use cin.get to input characters into buffer2 24 cin.get( buffer2, SIZE ); 25 26 // display buffer2 contents 27 cout << "The string read with cin.get was:" << endl 28 << buffer2 << endl; 29 return 0; 30 } // end main
|
Using Member Function getline
Member function getline operates similarly to the third version of the get member function and inserts a null character after the line in the character array. The getline function removes the delimiter from the stream (i.e., reads the character and discards it), but does not store it in the character array. The program of Fig. 15.6 demonstrates the use of the getline member function to input a line of text (line 15).
Figure 15.6. Inputting character data with cin member function getline.
(This item is displayed on pages 779 - 780 in the print version)
1 // Fig. 15.6: Fig15_06.cpp 2 // Inputting characters using cin member function getline. 3 #include 4 using std::cin; 5 using std::cout; 6 using std::endl; 7 8 int main() 9 { 10 const int SIZE = 80; 11 char buffer[ SIZE ]; // create array of 80 characters 12 13 // input characters in buffer via cin function getline 14 cout << "Enter a sentence:" << endl; 15 cin.getline( buffer, SIZE ); 16 17 // display buffer contents 18 cout << " The sentence entered is:" << endl << buffer << endl; 19 return 0; 20 } // end main
|
15.4.2. istream Member Functions peek, putback and ignore
The ignore member function of istream either reads and discards a designated number of characters (the default is one character) or terminates upon encountering a designated delimiter (the default delimiter is EOF, which causes ignore to skip to the end of the file when reading from a file).
The putback member function places the previous character obtained by a get from an input stream back into that stream. This function is useful for applications that scan an input stream looking for a field beginning with a specific character. When that character is input, the application returns the character to the stream, so the character can be included in the input data.
The peek member function returns the next character from an input stream but does not remove the character from the stream.
15.4.3. Type-Safe I/O
C++ offers type-safe I/O. The << and >> operators are overloaded to accept data items of specific types. If unexpected data is processed, various error bits are set, which the user may test to determine whether an I/O operation succeeded or failed. If operator << has not been overloaded for a user-defined type and you attempt to input into or output the contents of an object of that user-defined type, the compiler reports an error. This enables the program to "stay in control." We discuss these error states in Section 15.8.