13. Standard I/O Library


The most basic of all libraries in the whole of the standard C library is the standard I/O library. It's used for reading from and writing to files. I can see you're very excited about this.

So I'll continue. It's also used for reading and writing to the console, as we've already often seen with the printf() function.

(A little secret here--many many things in various operating systems are secretly files deep down, and the console is no exception. "Everything in Unix is a file!" :-))

You'll probably want some prototypes of the functions you can use, right? To get your grubby little mittens on those, you'll want to include stdio.h.

Anyway, so we can do all kinds of cool stuff in terms of file I/O. LIE DETECTED. Ok, ok. We can do all kinds of stuff in terms of file I/O. Basically, the strategy is this:

  1. Use fopen() to get a pointer to a file structure of type FILE*. This pointer is what you'll be passing to many of the other file I/O calls.
  2. Use some of the other file calls, like fscanf(), fgets(), fprintf(), or etc. using the FILE* returned from fopen().
  3. When done, call fclose() with the FILE*. This let's the operating system know that you're truly done with the file, no take-backs.

What's in the FILE*? Well, as you might guess, it points to a struct that contains all kinds of information about the current read and write position in the file, how the file was opened, and other stuff like that. But, honestly, who cares. No one, that's who. The FILE structure is opaque to you as a programmer; that is, you don't need to know what's in it, and you don't even want to know what's in it. You just pass it to the other standard I/O functions and they know what to do.

This is actually pretty important: try to not muck around in the FILE structure. It's not even the same from system to system, and you'll end up writing some really non-portable code.

One more thing to mention about the standard I/O library: a lot of the functions that operate on files use an "f" prefix on the function name. The same function that is operating on the console will leave the "f" off. For instance, if you want to print to the console, you use printf(), but if you want to print to a file, use fprintf(), see?

Wait a moment! If writing to the console is, deep down, just like writing to a file, since everything in Unix is a file, why are there two functions? Answer: it's more convenient. But, more importantly, is there a FILE* associated with the console that you can use? Answer: YES!

There are, in fact, three (count 'em!) special FILE*s you have at your disposal merely for just including stdio.h. There is one for input, and two for output.

That hardly seems fair--why does output get two files, and input only get one?

That's jumping the gun a bit--let's just look at them:

stdin

Input from the console.

stdout

Output to the console.

stderr

Output to the console on the error file stream.

So standard input (stdin) is by default just what you type at the keyboard. You can use that in fscanf() if you want, just like this:

/* this line: */
scanf("%d", &x);

/* is just like this line: */
fscanf(stdin, "%d", &x);

And stdout works the same way:

printf("Hello, world!\n");
fprintf(stdout, "Hello, world!\n"); /* same as previous line! */

So what is this stderr thing? What happens when you output to that? Well, generally it goes to the console just like stdout, but people use it for error messages, specifically. Why? On many systems you can redirect the output from the program into a file from the command line...and sometimes you're interested in getting just the error output. So if the program is good and writes all its errors to stderr, a user can redirect just stderr into a file, and just see that. It's just a nice thing you, as a programmer, can do.