|
|
The functions in Section 3S constitute the standard I/O library for C programs. In this section, we want to discuss standard I/O in a bit more detail. First, let's briefly define what I/O involves. It has to do with
Programs automatically start off with three open files: standard input, standard output, and standard error. These files with their associated buffering are called streams, and are designated stdin, stdout, and stderr, respectively. The shell associates all three files with your terminal by default.
This means that you can use functions and macros that deal with stdin, stdout, or stderr without having to open or close files. scanf, for example, reads a string from stdin; printf writes a string to stdout. Other functions and macros read from or write to files in different ways: character at a time, getc and putc; formatted, scanf and printf; and so on. You can specify that output be directed to stderr by using a function such as fprintf. fprintf works the same way as printf except that it delivers its formatted output to a named stream, such as stderr.
Any file other than standard input, standard output, and standard error must be explicitly opened by you before your program can read from or write to the file. You open a file with the standard library function fopen. fopen takes a path name, asks the system to keep track of the connection between your program and the file, and returns a pointer that you can then use in functions that perform other I/O operations.
The pointer is to a structure called FILE, defined in <stdio.h>, that contains information about the file: the location of its buffer, the current character position in the buffer, and so on. In your program, then, you need to have a declaration such as
FILE *fin;which says that fin is a pointer to a FILE. The statement
fin = fopen("filename", "r");associates a FILE structure with filename, the path name of the file to open, and returns a pointer to it. The ``"r"'' means that the file is to be opened for reading. This argument is known as the mode. There are modes for reading, writing, and both reading and writing.
In practice, the file open function is often included in an if statement:
if ((fin = fopen("filename", "r")) == NULL) (void)fprintf(stderr,"Cannot open input file %s\n", "filename");which takes advantage of the fact that fopen returns a NULL pointer if it cannot open the file. To avoid falling into the immediately following code on failure, you can call exit, which causes your program to quit:
if ((fin = fopen("filename", "r")) == NULL) { (void)fprintf(stderr,"Cannot open input file %s\n", "filename"); exit(1); }Once you have opened the file, you use the pointer fin in functions or macros to refer to the stream associated with the opened file:
int c; c = getc(fin);brings in one character from the stream into an integer variable called c. The variable c is declared as an integer even though we are reading characters because getc returns an integer. Getting a character is often incorporated in some flow-of-control mechanism such as
while ((c = getc(fin)) != EOF) . . .that reads through the file until EOF is returned. EOF, NULL, and the macro getc are all defined in <stdio.h>. getc and other macros in the standard I/O package keep advancing a pointer through the buffer associated with the stream; UnixWare and the standard I/O functions are responsible for seeing that the buffer is refilled if you are reading the file, or written to the output file if you are producing output, when the pointer reaches the end of the buffer.
Your program may have multiple files open simultaneously, 20 or more depending on system configuration. If, subsequently, your program needs to open more files than it is permitted to have open simultaneously, you can use the standard library function fclose to break the connection between the FILE structure in <stdio.h> and the path names of the files your program has opened. Pointers to FILE may then be associated with other files by subsequent calls to fopen. For output files, an fclose call makes sure that all output has been sent from the output buffer before disconnecting the file. exit closes all open files for you, but it also gets you completely out of your process, so you should use it only when you are sure you are finished.