C ungetc function
last modified April 6, 2025
The ungetc function is a powerful tool in C programming that allows
you to push characters back into an input stream. This capability is essential
for parsing operations where you need to "peek" ahead or undo a read. This
tutorial explores ungetc in depth, explaining its behavior,
limitations, and practical applications. Through clear examples, you'll learn how
to effectively use this function in your C programs.
What Is ungetc?
The ungetc function pushes a character back into the input stream,
making it available for subsequent read operations. It takes two parameters: the
character to push back and the stream pointer. The pushed-back character must be
read before any further input operations. Note that ungetc has
implementation-defined limits on how many characters can be pushed back
successively. Always check the return value to ensure the operation succeeded.
Basic ungetc Example
This simple example demonstrates the fundamental usage of ungetc.
#include <stdio.h>
int main() {
int ch;
printf("Enter a character: ");
ch = getchar(); // Read a character
if (ch != EOF) {
ungetc(ch, stdin); // Push it back
printf("You entered: ");
putchar(getchar()); // Read it again
}
return 0;
}
This program reads a character from standard input, pushes it back using
ungetc, then reads it again. The character is effectively "peeked"
without being consumed. Note that ungetc returns the character on
success or EOF on failure. The pushed-back character must be read
before any other input operations.
Using ungetc with File Streams
This example shows how to use ungetc with file streams.
#include <stdio.h>
int main() {
FILE *fp = fopen("data.txt", "r");
if (fp == NULL) {
perror("Error opening file");
return 1;
}
int ch = fgetc(fp); // Read first character
if (ch != EOF) {
ungetc(ch, fp); // Push it back
printf("First character: %c\n", fgetc(fp));
}
fclose(fp);
return 0;
}
Here, we open a file and read its first character. The ungetc
function pushes the character back into the file stream, allowing us to read it
again. This technique is useful when you need to examine a character before
deciding how to process it. Remember that file streams must be properly opened
and closed to avoid resource leaks.
Multiple ungetc Operations
This example demonstrates multiple pushback operations and their limitations.
#include <stdio.h>
int main() {
int ch;
printf("Enter a character: ");
ch = getchar();
if (ch != EOF) {
ungetc(ch, stdin); // First pushback
if (ungetc('X', stdin) == EOF) { // Second pushback
printf("Second ungetc failed\n");
}
printf("Reading back: ");
putchar(getchar()); // 'X'
putchar(getchar()); // original character
}
return 0;
}
This program attempts two ungetc operations. The standard guarantees
at least one successful pushback, but multiple pushbacks are
implementation-dependent. Here, we push back the original character and then try
to push 'X'. The characters are read in reverse order of being pushed. If the
second ungetc fails, it returns EOF.
ungetc in Number Parsing
This example shows how ungetc can help in parsing numbers.
#include <stdio.h>
#include <ctype.h>
int main() {
printf("Enter a number: ");
int ch;
int value = 0;
while ((ch = getchar()) != EOF && isdigit(ch)) {
value = value * 10 + (ch - '0');
}
if (ch != EOF) {
ungetc(ch, stdin); // Push back non-digit
}
printf("Parsed value: %d\n", value);
printf("Next character: %c\n", getchar());
return 0;
}
This program reads digits to form a number, then pushes back the first non-digit
character encountered. This allows the non-digit to be processed separately. The
ungetc function is particularly useful in lexical analysis where
you need to "put back" characters that don't belong to the current token. The
pushed-back character is available for the next read operation.
Error Handling with ungetc
This example demonstrates proper error handling with ungetc.
#include <stdio.h>
int main() {
int ch = getchar();
if (ch == EOF) {
printf("Read error or EOF\n");
return 1;
}
if (ungetc(ch, stdin) == EOF) {
printf("ungetc failed\n");
return 1;
}
printf("Successfully pushed back: %c\n", getchar());
return 0;
}
This code shows how to handle potential errors when using ungetc.
First, we check if getchar succeeded. Then we verify that
ungetc worked by checking its return value. Proper error handling
is crucial when working with input streams, as pushback operations might fail due
to various system limitations. Always check the return value of
ungetc to ensure the operation succeeded.
ungetc with fscanf
This example combines ungetc with fscanf for flexible input.
#include <stdio.h>
int main() {
int num;
char ch;
printf("Enter input (e.g., 123a): ");
if (scanf("%d", &num) == 1) {
scanf("%c", &ch); // Read next character
ungetc(ch, stdin); // Push it back
printf("Number: %d\n", num);
printf("Next character: %c\n", getchar());
}
return 0;
}
Here, we read a number with scanf, then the following character.
The character is pushed back with ungetc and read again. This
technique is useful when you need to parse mixed input formats. The
ungetc function allows you to "undo" the read of the character
after the number, giving you more control over input processing.
Implementing peek() with ungetc
This example shows how to create a peek function using ungetc.
#include <stdio.h>
int peek(FILE *stream) {
int ch = fgetc(stream);
if (ch != EOF) {
ungetc(ch, stream);
}
return ch;
}
int main() {
printf("Enter text: ");
int first = peek(stdin);
if (first != EOF) {
printf("First character will be: %c\n", first);
printf("Actual input: %c\n", getchar());
}
return 0;
}
The peek function reads a character and immediately pushes it back,
allowing you to examine the next character without consuming it. This is a common
requirement in parsers and scanners. The function returns EOF if
the end of file is reached or an error occurs. This implementation handles both
file streams and standard input effectively.
Best Practices for Using ungetc
- Check Return Values: Always verify that
ungetcsucceeds by checking its return value. - Mind the Limits: Remember that only one character pushback is guaranteed to work portably.
- Use Before Other Operations: Read pushed-back characters before performing other input operations.
- Avoid EOF Pushback: Never try to push
EOFback into the stream. - Combine with Parsing: Use
ungetcto simplify complex input parsing logic.
Source
This tutorial has explored the ungetc function in C, demonstrating
its versatility in input processing. From basic usage to advanced parsing
techniques, ungetc provides valuable control over character input
streams. Mastering this function will enhance your ability to create robust input
processing routines in your C programs.
Author
List C Standard Library.