CS110 Lab: EOF Loops, Nested Loops


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
To test the state of a stream, the stream name can be used in an expression. The expression returns a true value if the state is ok and a false value if the state is in the fail state. 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 expression returns a false value, the program terminates. When it returns a true value, the program continues reading the data item from the file. Here is a sample program that reads floating point data values from a file and outputs the sum and average of the 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 successfully." << 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 successfully." << endl;
       return 2;
    }

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

    inData >> val;  // read in the first value

    while (inData)   //while previous input succeeded ...
    {
       sum = sum + val;
       count++;
       inData  >> val;	// read in the next value
    }

    if ( count != 0)
       average = sum / count;
       else
       average = 0;

    outData  << sum  << average << endl;	
	// outputs sum and average

    inData.close();
    outData.close();

    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 program is exited as soon as a value is returned. Therefore, returning 0 value means normal completion of a program; and 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 read the data, and sum up the values, and record the number of items read until the EOF is encountered.

You can use the pico or vi text editor to create the input data file according to the requirements of the data type and the format specified in your program. The input data file must exist and contain correct data. Otherwise, the input stream will fail.

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

3.2
4.6
5.5
6.6
7.7
8.8
9.8
Run the program and find the sum and average of your input data.

Nested Loops

The body of a loop can contain any type of statement including another loop such as a While loop, a Do-while loop, or a For loop. A loop inside another loop is called a nested loop.

The following program counts the number of characters on each line in a file. We know that the I/O manipulator endl forces the next character sent to the output stream to begin a new line. How can we recoganize a new line in 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 <iostream>
#include <fstream>
using namespace std;

int main()
{
    int lineNo;
    char character;
    int number;
    ifstream inData;  //declares input stream

    // bind the input stream name inData to the file "Input.txt"
    inData.open("Input.txt");
    if (!inData)
    {
       cout << "Can't open the input file successfully." << endl;
       return 1;
    }
 
    lineNo = 0;

    //Use get function to read data from file "Input.txt"
    inData.get(character);

    //while the input stream is not in the fail state
    //e.g. 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);
    }

    inData.close();

    return 0;
}

Back to Top



Copyright: Department of Computer Science, University of Regina.