Previous: 3.4 Interacting with the Operating System
Up: 3.4 Interacting with the Operating System
Next: 3.4.2 Standard Files and Redirection
Previous Page: 3.4 Interacting with the Operating System

3.4.1 Standard Files and EOF

In our payroll programs, we used a sentinel value of id number, namely 0, to indicate the end of input data. There are many instances when it is not possible to use a special sentinel value of input data to terminate the input. For example, suppose we wish to read a sequence of numbers and determine the largest of them. It is impossible to select any one number as a signal to terminate input since any selected number may be one of the valid numbers in our sequence and may appear before the entire sequence of numbers is exhausted. We need a way to indicate that the end of input is reached without entering any special value of input which may also be valid data.

C provides such mechanism to indicate the end of data input through the way it handles all input and output. All data read by a C program or written from a program can be considered to be simply a stream or sequence of characters, i.e. symbols we use to type or print information: alphabetic letters, digits, punctuations, etc. This stream of characters is called a file and is organized like any other file in the system. Three files, called standard input, standard output, and standard error, are predefined files available to all programs. By default, standard input is the keyboard, and standard ouput is the screen. The function scanf() reads data from the standard input file, and printf() writes data to the standard output file. Run time error messages are written to standard error, which is also the screen, by default.

The end of a file is indicated by a special marker which is an unusual character not commonly used for any other purpose. When input is typed at the keyboard, an end of file mark is indicated by what is called a control character. A control character is typed by pressing the control key, (CTRL), and pressing another key while keeping CTRL key pressed. For example, control-A is entered by pressing CTRL and pressing A while keeping CTRL pressed. Control characters are displayed on screen or paper by a caret followed by a letter. For example, control-A is written as '136A. The Control character entered on a keyboard to indicate an end of file is '136D on most Unix machines and '136Z on DOS machines. A keyboard file (stream) with an end of file keystroke is shown in Figure 3.12. Here, three lines of input are represented, followed by the end of file marker as if the user had typed:

How does scanf() inform the calling function that an end of file has been reached? It does so by returning a special value to indicate an end of file. The function scanf() is just like any other function in C; it has arguments passed to it and it returns a value. So far, we have simply ignored whatever value has returned. Normally, when scanf() reads data, it returns a value to indicate the number of data items read successfully. We can save this value returned by scanf() and examine whether all data items have been read. For example, consider:

flag = scanf("%d", &n);
     flag = scanf("%d %f %d", &n, &y, &id);
Assuming that both the above statements read data items successfully, then the first scanf() will return 1 since it reads one decimal integer, and the second will return 3 since it reads three data items, two int's and a float. We have not used this value so far, but we can use it to check if a correct number of items are read.

When scanf() detects the special end of file marker, it returns a value of either 0 or -1 (depending on implementation). The actual value returned is defined as a macro called EOF in the file stdio.h.

We can now write a loop that terminates when the end of standard input file is reached.

#include <stdio.h>
     ...
     flag = scanf();
     while (flag != EOF) {
          ...
          flag = scanf();
     }
The value returned by scanf() is saved in the variable flag. The loop repeats until flag receives the value EOF. The above code is portable to any implementation since the correct value of is defined in stdio.h in every implementation. We can now write a program that uses end of file to terminate reading of data.

Task

BIG: Find the largest absolute value in a sequence of integers typed in by the user. An end of file keystroke terminates the input.

The algorithm maintains the current largest absolute value. Each time a new number is read, the absolute value of the item read is compared with the largest value, and if necessary the largest value is updated. The algorithm uses a loop that is terminated when an end of file keystroke is typed. Here is the algorithm.

initialize largest to 0
     read first integer, n
     while there is still data
          compare absolute value of n and largest, update largest
          read next integer
     print largest
We will need a function absolute() which takes an integer argument n, and returns its absolute integer value. Notice we initialize our largest absolute value to 0, since that is the smallest absolute value we can ever encounter. The entire program is shown in Figure 3.13 and a sample session is:

In our program, main() first prompts the user to type integers, and it also tells the user how to terminate the input. It is best to assume that the user does not know how to press a keystroke for EOF (however, in the future we will omit this reminder and assume the user knows the correct EOF character). The prompt is written by:

printf("Type integers, EOF to quit: "
               "^Z for DOS, ^D for Unix\n");
Observe that the argument of printf() consists of two adjoining strings of characters, each in double quotes. When the compiler encounters two adjoining strings, it replaces them by a concatenated string, i.e. it joins them together into a single string:
"Type integers, EOF to quit: ^Z for DOS, ^D for Unix\n"
When a string gets too large, it is best to split it into two adjoining strings, since strings cannot be broken across lines.

After the prompt, main() reads the first integer. The while loop tests for the end of the input and compares the value of largest and the absolute value of the last number read, n. If necessary largest is updated, a new number is read, and so forth. The loop is terminated when an end of file character ('136D or '136Z) is encountered by the function scanf() and it returns a value EOF. Remember, only the value of flag, NOT that of n, gets the value, EOF. The value of n will remain unchanged from its previous value when scanf() encounters end of file. Finally, the largest absolute value is printed out.

We have seen that scanf() returns a value of items read or EOF. It also performs the task of reading one or more items, converting them to internal form, and storing them at specified addresses. This additional task does not directly contribute to the returned value and is called a side effect. Functions may be used solely for their side effects, solely for their returned values, or for both side effects and returned values. For example, we use printf() for its side effect and ignore its value. We also frequently ignore the value of scanf(). In this section, we have used scanf() for both its side effect as well as its return value.



Previous: 3.4 Interacting with the Operating System
Up: 3.4 Interacting with the Operating System
Next: 3.4.2 Standard Files and Redirection
Previous Page: 3.4 Interacting with the Operating System

tep@wiliki.eng.hawaii.edu
Wed Aug 17 08:21:42 HST 1994