EOF Loop

We know any of the following can cause an input stream to enter the fail state:
  1. Invalid input data
  2. An attempt to read beyond the end of a file
  3. An attempt to open a nonexistent file to input
C++ provides a way to test the state of a stream: The stream name used in the expression returns true value if the state is ok and false value if the state is in the fail state.

When the test returns a false value, the program terminates. When it returns a true value, the program can keep reading the data item from the file. Here is an example program that reads floating point data values from a file and output the sum and average of these numbers.


// Program IODemo demonstrates how to use EOF

#include <iostream>
#include <fstream>
using namespace std;

int main()
{
    cout  << fixed  << showpoint;

    float val;
    float sum = 0;
    float average = 0;
    int count = 0;
    ifstream inData;			// declares input stream
    ofstream outData;			// declares output stream

    // binds program variable inData to file "input.txt"
    inData.open("input.txt");

    //Testing the state of the stream
    //true means the last I/O operation on that stream succeeded
    //false means the last I/O operation on that stream failed
    if (!inData)
    {
       cout << "Can't open the input file successfuly." << endl;
       return 1;
    }

    // binds program variable outData to file "output.txt"
    outData.open("output.txt");

    //Testing the state of the stream
    if (!outData)
    {
       cout << "Can't open the output file successfuly." << endl;
       return 2;
    }

    //Read value from the input file
    //Loop terminates when EOF is encountered

    while (inData)   //while previous input succeeded ...
    {
       inData  >> val;	// inputs values
       sum = sum + val;
       count++;
    }
    average = sum / count;

    outData  << sum << average << endl;
    return 0;
}

Notice that inData and outData are identifiers in the program; "input.txt" and "output.txt" are character strings. input.txt is the name that was used when the input data file was created; output.txt is the name of the file where the answers are stored.

If the input file input.txt cannot be found, 1 is returned to the operating system. If the output file output.txt cannot be opened or created, 2 is returned to the operating system. If there is no input and output error, 0 is returned to the operating system. Notice that the main is exited as soon as a value is returned. Therefore, Returning 0 value means normal completion of a program; returning any other value signals an error. When you write your own program, you may choose the value to return to indicate different error conditions.

While input data file has correct data items, the program will keep reading the data and sum them up and record the number of items read until the EOF is encountered.

You can use pico or vi text editor to create the input data file according to the requirement of the data type and format in your program. Input data file must exist and contain correct data. Otherwise, you will get input failure.

For example, in the preceding IODemo program, the input file look like this:

5.5
6.6
7.7
8.8
9.8
You may run the program and find sum and average of your input data. You should find this program familiar.

Nested Loops

The body of the loop can contain any type of statement including another While statement. A loop is inside another loop is called nested loop.

The following program counts the number of characters on each line in a file. We know that the manipulator endl forces the next character sent to the output stream to begin a new line. How can we recoganize a new line on the input stream? A new line begins following the symbol '\n'. We must be sure to use function get defined in iostream, not the extraction operator, to input each character.


// Program LineCt counts the number of characters per line
// and the number of lines in a file.
// Assumption:  There is a '\n' before the EOF.
#include 
#include 
using namespace std;

int main()
{
    int lineNo;
    char character;
    int number;
    ifstream inData;

    inData.open("Data.In");
    lineNo = 0;
    inData.get(character);

    //while not EOF, go into the loop
    while (inData)
    {
	lineNo++;
	number = 0;


	//while not "end of line", go into the loop
	while (character != '\n')
	{
	    number++;
	    inData.get(character);
	}
	cout << "Line " << lineNo  << " contains "
	     << number  << " characters."  << endl;
	inData.get(character);
    }
    return 0;
}