Every time a character is read from a stream by a function like
getc, the file position indicator advances by 1. It is possible
to reverse the motion of the file position indicator with the function
ungetc, which steps the file position indicator back by one
byte within the file and reverses the effect of the last character
read operation. (This is called unreading the character or
pushing it back onto the stream.)
The intended purpose is to leave the indicator in the correct file
position when other functions have moved too far ahead in the stream.
Programs can therefore peek ahead, or get a glimpse of the input
they will read next, then reset the file position with ungetc.
On GNU systems, you cannot call ungetc twice in a row without
reading at least one character in between; in other words, GNU only
supports one character of pushback.
Pushing back characters does not change the file being accessed at all;
ungetc only affects the stream buffer, not the file. If
fseek, rewind, or some other file positioning function is
called, any character due to be pushed back by ungetc is
discarded.
Unreading a character on a stream that is at end-of-file resets the
end-of-file indicator for the stream, because there is once again a
character available to be read. However, if the character pushed back
onto the stream is EOF, ungetc does nothing and just
returns EOF.
Here is a code example that reads all the whitespace at the beginning of
a file with getc, then backs up one byte to the first
non-whitespace character, and reads all following characters up to a
newline character with the getline function. (See getline, for
more information on that function.)
#include <stdio.h>
int main()
{
int in_char;
FILE *my_stream;
char *my_string = NULL;
size_t nchars = 0;
my_stream = fopen ("snazzyjazz.txt", "w");
fprintf (my_stream, " Here's some non-whitespace.\n");
/* Close stream; skip error-checking for brevity of example */
fclose (my_stream);
my_stream = fopen ("snazzyjazz.txt", "r");
/* Skip all whitespace in stream */
do
in_char = getc (my_stream);
while (isspace (in_char));
/* Back up to first non-whitespace character */
ungetc (in_char, my_stream);
getline (&my_string, &nchars, my_stream);
/* Close stream; skip error-checking for brevity of example */
fclose (my_stream);
printf ("String read:\n");
printf ("%s", my_string);
return 0;
}
The code example will skip all initial whitespace in the file
snazzyjazz.txt, and display the following text on standard
output: