16.3: Character Input and Output (getchar, putchar, etc.)

Character-at-a-time input and output is simple and straightforward. The getchar function reads the next character from the standard input; getc(fp) reads the next character from the stream fp. Both return the next character or, if the next character can't be read, the non-character constant EOF, which is defined in <stdio.h>. (Usually the reason that the next character can't be read is that the input stream has reached end-of-file, but it's also possible that there's been some I/O error.) Since the value EOF is distinct from all character values, it's important that the return value from getc and getchar be assigned to a variable of type int, not char. Don't declare the variable to hold getc's or getchar's return value as a char; don't try to read characters directly into a character array with code like

	while(i < max && (a[i] = getc(fp)) != EOF)	/* WRONG, for char a[] */
The code may seem to work at first, but some day it will get confused when it reads a real character with a value which seems to equal that which results when the non-char value EOF is crammed into a char.

One more reminder about getchar: although it returns and therefore seems to read one character at a time, it typically delivers characters from internal buffers which may hold more characters which will be delivered later. For example, most command-line-based operating systems let you type an entire line of input, and wait for you to type the RETURN or ENTER key before making any of those characters available to a program (even if the program thought it was doing character-at-a-time input with calls to getchar). There are, of course, ways to read characters immediately (without waiting for the RETURN key), but they differ from operating system to operating system.

Writing single characters is just as easy as reading: putchar(c) writes the character c to standard output; putc(c, fp) writes the character c to the stream fp. (The character c must be a real character. If you want to ``send'' an end-of-file condition to a stream, that is, cause the program reading the stream to ``get'' end-of-file, you do that by closing the stream, not by trying to write EOF to it.)

Occasionally, when reading characters, you sometimes find that you've read a bit too far. For example, if one part of your code is supposed to read a number--a string of digits--from a file, leaving the characters after the digits on the input stream for some other part of the program to read, the digit-reading part of the program won't know that it has read all the digits until it has read a non-digit, at which point it's too late. (The situation recalls Dave Barry's recipe for ``food heated up'': ``Put the food in a pot on the stove on medium heat until just before the kitchen fills with black smoke.'') When reading characters with the standard I/O library, at least, we have an escape: the ungetc function ``un-reads'' one character, pushing it back on the input stream for a later call to getc (or some other input function) to read. The prototype for ungetc is

	int ungetc(int c, FILE *fp)
where c is the character which is to be pushed back onto the stream fp. For example, here is a code scrap that reads digits from a stream (and converts them to the corresponding integer), stopping at the first non-digit character and leaving it on the input stream:
#include <ctype.h>

int c, n = 0;
while((c = getchar()) != EOF && isdigit(c))
	n = 10 * n + (c - '0');
if(c != EOF)
	ungetc(c, stdin);
It's only guaranteed that you can push one character back, but that's usually all you need.

Read sequentially: prev next up top

This page by Steve Summit // Copyright 1996-1999 // mail feedback