Simplicity is one of the attractions of input and output redirection; there's no need to open a file, close a file, or perform any other explicit file operations. Unfortunately, redirection is too limited for many applications. When a program relies on redirection, it has no control over its files; it doesn't even know their names. Worse still, redirection doesn't help if the program needs to read from two files or write to two files at the same time.
When redirection isn't enough, we'll end up using the file operations that
provides. In this section, we'll explore these operations,
which include opening a file, closing a file, changing the way a file is
buffered, deleting a file, and renaming a file.
Opening a File
FILE *fopen(const char * restrict filename, const char * restrict mode);
Opening a file for use as a stream requires a call of the f open function, f open's first argument is a string containing the name of the file to be opened. (A "file name" may include information about the file's location, such as a drive specifier or path.) The second argument is a "mode string" that specifies what operations we intend to perform on the file. The string "r", for instance, indicates that data will be read from the file, but none will be written to it.
Note that restrict appears twice in the prototype for the fopen function, restrict, which is a C99 keyword, indicates that filename and mode should point to strings that don't share memory locations. The C89 prototype for f open doesn't contain restrict but is otherwise identical, restrict has no effect on the behavior of f open, so it can usually just be ignored. In this and subsequent chapters, I'll italicize restrict as a reminder that it's a C99 feature.
Windows programmers: Be careful when the file name in a call of f open includes the \ character, since C treats \ as the beginning of an escape sequence. The call
will fail, because the compiler treats \t as a character escape. (\p isn't a valid character escape, but it looks like one. The C standard states that its meaning is
undefined.) There are two ways to avoid the problem. One is to use \\ instead of \:
The other technique is even easier just use the / character instead of \:
Windows will happily accept / instead of \ as the directory separator.
fopen returns a file pointer that the program can (and usually will) save in a variable and use later whenever it needs to perform an operation on the file. Here's a typical call of fopen, where fp is a variable of type FILE *:
fp = fopen("in.dat", "r"); /* opens in.dat for reading */
When the program calls an input function to read from in.dat later, it will supply fp as an argument.
When it can't open a file, fopen returns a null pointer. Perhaps the file doesn't exist, or it's in the wrong place, or we don't have permission to open it.
Never assume that a file can be opened; always test the return value of fopen to make sure it's not a null pointer.