So far, when a call was made to the scanf function by one of the programs in this book, the data that was requested by the call was always read in from your terminal. Similarly, all calls to the printf function resulted in the display of the desired information in your terminal window. In this section, you learn how you can read and write data from and to a file instead.
1. Redirecting I/O to a File
Both read and write file operations can be easily performed under many operating systems, such as Unix and Windows, without anything special being done at all to the program. If you want to write all your program results into a file called data, for exam- ple, all that you need to do under Unix or Windows if running in a terminal window is to redirect the output from the program into the file data by executing the program with the following command:
prog > data
This command instructs the system to execute the program prog but to redirect the out- put normally written to the terminal into a file called data instead. So, any values displayed by printf do not appear in your window but are instead written into the file called data.
To see how this works, type in the very first program you wrote, Program 3.1, and compile the program in the usual way. Now execute the program as you normally would by typing in the program name (assume it’s called prog1):
If all goes well, you should get the output
Programming is fun.
displayed in your window. Now type in the following command:
prog1 > data
This time, notice that you did not get any output at the terminal. This is because the output was redirected into the file called data. If you now examine the contents of the file data, you should find that it contains the following line of text:
Programming is fun.
This verifies that the output from the program went into the file data as described pre- viously.You might want to try the preceding sequence of commands with a program that produces more lines of output to verify that the preceding process works properly in such cases.
You can do a similar type of redirection for the input to your programs. Any call to a function that normally reads data from your window, such as scanf and getchar, can be easily made to read its information from a file. Program 5.8 was designed to reverse the digits of a number. The program uses scanf to read in the value of the number to be reversed from the terminal.You can have the program instead get its input from a file called number, for example, by redirecting the input to the program when the program is executed. If the program is called reverse, the following command line should do the trick:
reverse < number
If you type the number 2001 into a file called number before issuing the preceding com- mand, the following output appears at the terminal after this command is entered:
Enter your number.
Notice that the program requested that a number be entered but did not wait for you to type in a number. This is because the input to the program—but not its output—was redirected to the file called number. Therefore, the scanf call from the program had the effect of reading the value from the file number and not from your terminal window. The information must be entered in the file the same way that it would be typed in from the terminal. The scanf function itself does not actually know (or care) whether its input is coming from your window or from a file; all it cares about is that it is properly formatted. Naturally, you can redirect the input and the output to a program at the same time.
reverse < number > data
causes execution of the program contained in reverse to read all program input from the file number and to write all program results into the file data. So, if you execute the previous command for Program 5.8, the input is once again taken from the file number, and the output is written into the file data.
The method of redirecting the program’s input and/or its output is often practical. For example, suppose you are writing an article for a magazine and have typed the text into a file called article. Program 10.8 counted the number of words that appeared in lines of text entered at the terminal.You could use this very same program to count the number of words in your article simply by typing in the following command:2
wordcount < article
Of course, you have to remember to include an extra carriage return at the end of the article file because your program was designed to recognize an end-of-data condition by the presence of a single newline character on a line.
Note that I/O redirection, as described here, is not actually part of the ANSI defini- tion of C. This means that you might find operating systems that don’t support it. Luckily, most do.
2. End of File
The preceding point about end of data is worthy of more discussion. When dealing with files, this condition is called end of file. An end-of-file condition exists when the final piece of data has been read from a file. Attempting to read past the end of the file might cause the program to terminate with an error, or it might cause the program to go into an infinite loop if this condition is not checked by the program. Luckily, most of the functions from the standard I/O library return a special flag to indicate when a program has reached the end of a file. The value of this flag is equal to a special name called EOF, which is defined in the standard I/O include file <stdio.h>.
As an example of the use of the EOF test in combination with the getchar function, Program 16.2 reads in characters and echoes them back in the terminal window until an end of file is reached. Notice the expression contained inside the while loop. As you can see, an assignment does not have to be made in a separate statement.
Program 16.2 Copying Characters from Standard Input to Standard Output
// Program to echo characters until an end of file
int main (void)
while ( (c = getchar ()) != EOF )
If you compile and execute Program 16.2, redirecting the input to a file with a com- mand such as
copyprog < infile
the program displays the contents of the file infile at the terminal. Try it and see! Actually, the program serves the same basic function as the cat command under Unix, and you can use it to display the contents of any text file you choose.
In the while loop of Program 16.2, the character that is returned by the getchar function is assigned to the variable c and is then compared against the defined value EOF. If the values are equal, this means that you have read the final character from the file.
One important point must be mentioned with respect to the EOF value that is returned by the getchar function: The function actually returns an int and not a char. This is because the EOF value must be unique; that is, it cannot be equal to the value of any character that would normally be returned by getchar. Therefore, the value returned by getchar is assigned to an int and not a char variable in the preceding program. This works out okay because C allows you to store characters inside ints, even though, in general, it might not be the best of programming practices.
If you store the result of the getchar function inside a char variable, the results are unpredictable. On systems that do sign extension of characters, the code might still work okay. On systems that don’t do sign extension, you might end up in an infinite loop.
The bottom line is to always remember to store the result of getchar inside an int so that you can properly detect an end-of-file condition.
The fact that you can make an assignment inside the conditional expression of the while loop illustrates the flexibility that C provides in the formation of expressions. The parentheses are required around the assignment because the assignment operator has lower precedence than the not equals operator.
Source: Kochan Stephen G. (2004), Programming in C: A Complete Introduction to the C Programming Language, Sams; Subsequent edition.