Reading to Input Failure (the End-of-file Method) The fourth method, called the end-of-file method (also called "reading to input failure") has the computer test for the actual end of the set of data. When the program tries to read past the last value in the file, the end-of-file condition is true. One advantage of the end-of-file method is that the computer, rather than the programmer, handles the details of detecting the end of the set of data. No phony values are needed, and the person entering the data does not have to know how many values there are. The method can be used when reading from an input stream or a file stream, and whether the program is reading individual numbers, strings, or characters (see its use with getline() and get() in Chapter 8). When you read from a stream or a file stream, the stream variable gets a value indicating the success or failure of the attempt to read. The attempt can fail either because you have come to the end of the input or because the data value read in cannot be appropriately converted to the type needed by the variable into which it is to be stored. The value of the stream variable can be used in a standard structured read loop so that the program will fall out of the loop at input failure. Reading from an Input File Stream Example 7-18 shows how to read from an input file stream until input failure. EXAMPLE 7-18: This example reads data into num from the file stream in7 (associated with an input file called "in7.dat") and writes it to file stream out7. This process continues until the attempt to read from the file fails; at that point, the program falls out of the loop. ifstream in7("in7.dat"); ofstream out7("out7.out"); in7 >> num; while (in7) { // while a value was successfully read out7 << num; // process it in7 >> num; // try to get another value } in6.close(); out6.close(); The stream variable in7 reports failure when the program tries to read past the last data value in the input stream (that is, when the program tries to read a value and there is no value present in the file). If there is a data value, the program enters the loop, reads and processes the value. If there is no value left in the file, the program falls out of the loop. ^^^^^ Reading Groups of Values in a Data Set Some programs read and process groups of data (for example reading three temperatures and comparing them, or reading three grades and averaging them). There might be 15 to 20 groups of data in the file. Reading groups of values from a file can be accomplished simply by using one statement that reads the entire group of values. This is not considered acceptable when reading data interactively, because of the need to use prompts, but it is fine when reading from a file. EXAMPLE 7-19: int num1, num2, num3, result; ifstream infile("ftest.dat"); infile >> num1 >> num2 >> num3; while (infile) { ... infile >> num1 >> num2 >> num3; } // process values here The program reads three values at a time from infile; if the read is successful, the program enters the loop, processes those three values, and goes to get three more. The problem with this method is that it does not tell which value caused input failure; as long as that doesn't matter to the programmer, this is acceptable. ^^^^^ Example 7-20 shows how to use the end-of-file method in the readdata() function from Program 7, reading from an input file stream into an array. EXAMPLE 7-20: This version of readdata() reads data into array num from the file stream in7 (associated with an input file called "in7.dat") until the attempt to read from the file fails; at that point, the program falls out of the loop. This version does not ask the user to enter the number of values in advance, but instead counts the number of values as they are read in. When the program reaches the end of file, n contains the number of values read in. // Function readdata: reads from a data file until end-of-file // array num gets gets values from the file; // parameter n carries back to main the number of values read in void readdata(int num[], int &n) { ifstream in7("in7.dat"); n = 0; in7 >> num[n]; while (in7) { successfully read n++; in7 >> num[n]; } in7.close(); return; } // while a value was // process it // try to get another value The stream variable in7 reports failure when the program tries to read past the last data value in the input stream (that is, when the program tries to read a value and there is no value present in the file). If there is a data value, the program enters the loop, reads and processes the value. If there is no value left in the file, the program falls out of the loop. If the data file contains the values 6 25, the first read statement gives num[0] the value 6 and sets in7 to report success. The program enters the loop, increments n to 1 and reads 25 into num[1]. Since the read is successful, in7 again reports success, the program again enters the loop and increments n to 2. When the program tries to read another value, the attempt to read will fail, in7 will get a value indicating failure, and the program will fall out of the loop without giving a value to num[2]. There will be values in num[0] and num[1], and n will be 2. ^^^^ Using the End-of-file Method with cin; Signaling End-of-File When reading from cin, the user must enter a special value, called the end-of-file character, to signal that there are no more data values. When the program reads this special value, the program inteprets the value to mean that there are no more values to read in. The end-of-file character is entered by pressing <Ctrl>-z in Windows or DOS or <Ctrl>-d in Unix. The user must enter the end-of-file character when the program requests a data value. When the program reads this character, it stops looking for data values. Note: The user does not need to do anything special to mark the end of an actual input file, since the computer can determine by itself that it has reached the end, and some editors supply an end-of-file character. Reading from cin until Input Failure Example 7-21 shows a simple loop that reads from the stream variable cin until input failure. EXAMPLE 7-21: This program reads values from cin and writes them to cout until the attempt to read fails; at that point, the program falls out of the loop. In the loop, the program counts the number of values as they are read in. When the user has run out of data, he or she enters the end-of-file character, signaling end-of-file and terminating the loop. When the loop terminates, n contains the number of values read in. int n = 0,num; cout << "Enter a number> "; cin >> num; while (cin) { // while a value was successfully read cout << num << endl; // process it n++; cin >> num; // try to get another value } cout << n << " values were entered" << endl; Suppose the user enters 5 and then 12. First num gets the value 5, and cin has a value indicating success; the program enters the loop, prints 5, counts it, and goes to read another value. The next value entered into num is 12. At the top of the loop, cin again reports success, and the program enters the loop, prints 12, and counts it. The next time the program asks for a value, the user presses <Ctrl>-z in Windows (or <Ctrl>-d in Unix). The program interprets this to mean that there are no more data values; as a result, cin reports failure, and the program falls out of the loop and prints "2 values were entered". ^^^^^