13.13. ungetc()

Pushes a character back into the input stream.

Prototypes

#include <stdio.h>
int ungetc(int c, FILE *stream);

Description

You know how getc() reads the next character from a file stream? Well, this is the opposite of that--it pushes a character back into the file stream so that it will show up again on the very next read from the stream, as if you'd never gotten it from getc() in the first place.

Why, in the name of all that is holy would you want to do that? Perhaps you have a stream of data that you're reading a character at a time, and you won't know to stop reading until you get a certain character, but you want to be able to read that character again later. You can read the character, see that it's what you're supposed to stop on, and then ungetc() it so it'll show up on the next read.

Yeah, that doesn't happen very often, but there we are.

Here's the catch: the standard only guarantees that you'll be able to push back one character. Some implementations might allow you to push back more, but there's really no way to tell and still be portable.

Return Value

On success, ungetc() returns the character you passed to it. On failure, it returns EOF.

Example

// read a piece of punctuation, then everything after it up to the next
// piece of punctuation.  return the punctuation, and store the rest
// in a string
//
// sample input: !foo#bar*baz
// output:  return value: '!', s is "foo"
//          return value: '#', s is "bar"
//          return value: '*', s is "baz"
//

char read_punctstring(FILE *fp, char *s)
{
    char origpunct, c;
    
    origpunct = fgetc(fp);

    if (origpunct == EOF) // return EOF on end-of-file
        return EOF;

    while(c = fgetc(fp), !ispunct(c) && c != EOF) {
        *s++ = c; // save it in the string
    }
    *s = '\0'; // nul-terminate the string!

    // if we read punctuation last, ungetc it so we can fgetc it next
    // time:
    if (ispunct(c))
        ungetc(c, fp);
    }

    return origpunct;
}

See Also

fgetc()