File Input

Input streams

Having created and opened your file for input as in the earlier discussion, your program can now read data from the file in the same way it read data from cin -- using the stream extraction operator >>. int int1; string s1; inStream >> int1; inStream >> s1; The function getline( ) may also be used with streams to read strings that include whitespace. getline( inStream, s1 );

A common I/O Pitfall

Recall that the extraction operator >> has two important characteristics
  1. It skips leading whitespace (including the newline character)
  2. It stops when it sees the next whitespace, but leaves that whitespace (including the newline) for the next input
When all the data in the file is the same type (numeric or text), simply using operator >> is best and easiest way.

For example, if our input file looked like this

5 42 77 63 22 86 47 we could write code like this to read all the integers for (int i = 0; i < 7; i++) { int value; inStream >> value; // do something with value } or if the file contained all strings now is the time for all good men to come to the aid of their party we could write this code for (int i = 0; i < 16; i++) { string word; inStream >> word; // do something with word } In fact, as long we are reading each piece of data (surrounded by whitespace) as a single entity, then opeator >> works just fine.

When using getline( ) and the extraction operator ( >> ) together to perform input, you must use extreme care to read the stream (user input or input file) properly. Consider the following code

int age; string name; cout << "Input your age and first name"; cin >> age; getline( cin, name ); If the user types 42 Bob Smith the result will not be what you expect and not what you want. The variable age will indeed contain the value 42, but name will be empty.

The problem is two-fold

  1. The statement cin >> age; does not read in the newline character at the end of the first input line. It just reads 42.
  2. getline(cin, name ); stops reading when it sees a newline character
These two behaviors result in getline(cin, name); reading no characters at all and therefore name is empty.
The solution is to read and discard the newline character before using getline(). This is accomplished with the function cin.ignore(). The cin.ignore() function can be used in several ways. For our purposes, we can use cin.ignore( ); to read and discard the next character (which should be the newline character) or cin.ignore( 1000, '\n'); which reads and discards the next 1000 characters up to and including the first newline character it sees. The ignore() function also works with file streams (ifstream) objects.

Checking for end-of-file

There are two basic ways of checking for end-of-file (eof) when reading from a file. Incorrect code may have problems when the input file contains "blank lines" at the end. Incorrect code will appear to read the last line of input twice.

The general approach (see text page 513) is to use a "priming read" and check for eof as a condition of a 'while loop'.

string name; inStream >> name; while( !inStream.eof() ) { // do something with name // read the next name inStream >> name; } An alternative that works especially well when getline() is not involved is the following code. This code make use of the fact that using operator >> returns a boolean value that tells us if the read was successful. string name; while( inStream >> name ) { // do something with name }

Last Modified: Monday, 28-Aug-2006 10:15:54 EDT