Exercise 4-9. Our
getchandungetchdo not handle a pushed-backEOFcorrectly. Decide what their properties should be if anEOFis pushed back, then implement your decision.
The bug: K&R’s original implementation uses char buf[BUFSIZE]. When ungetch(EOF) is called, EOF (typically -1) is stored as char. On platforms where char is unsigned, -1 wraps to 255, which is not EOF when read back. The result is corrupted input on any platform where char is unsigned (ARM, many embedded targets).
The fix: change the buffer type from char[] to int[] so that EOF (-1) is preserved exactly. The decision: pushing back EOF should cause the next getch to return EOF, faithfully representing the end-of-file condition.
Solution
/* K&R Exercise 4-9 — getch/ungetch that handle pushed-back EOF
* Compile: gcc -ansi -Wall ex4-9.c -o ex4-9 */
#include <stdio.h>
#define BUFSIZE 100
static int buf[BUFSIZE]; /* int[], NOT char[] — preserves EOF (-1) */
static int bufp = 0;
int getch(void)
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int c)
{
if (bufp >= BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++] = c;
}
int main(void)
{
int c;
/* Push back a regular character then EOF */
ungetch('A');
ungetch(EOF);
c = getch();
printf("first getch: %s\n", c == EOF ? "EOF" : "not EOF"); /* EOF */
c = getch();
printf("second getch: %c\n", c); /* A */
return 0;
}
Why char Fails
static char cbuf[100]; /* BROKEN on unsigned-char platforms */
/* ungetch(EOF): stores (char)(-1) = 255 (unsigned) or -1 (signed) */
/* getch returns 255, not EOF, on unsigned-char platforms */
/* safe cast: (unsigned char)(-1) != EOF */
static int ibuf[100]; /* CORRECT: int preserves -1 as -1 */
Compile and Run
gcc -ansi -Wall ex4-9.c -o ex4-9
./ex4-9
Sample Output
first getch: EOF second getch: A
What This Exercise Teaches
- Signed vs unsigned char — the C standard leaves
charsignedness implementation-defined; code that depends on it being signed is non-portable - Why
getcharreturnsint— exactly this reason: it must be able to return all 256 character values and EOF (-1), which requires more than 8 bits;intis the correct type for any variable holding a character-or-EOF - Designing for edge cases — the exercise forces you to think about what the correct behaviour should be before implementing; choosing to propagate EOF faithfully is the right answer here
Set Up Your C Environment
← Exercise 4-8 |
Chapter 4 Solutions |
Exercise 4-10 →
Book: The C Programming Language, 2nd Ed — Kernighan & Ritchie