Exercise 4-11. Modify
getopso that it doesn’t need to useungetch. Hint: use an internalstaticvariable.
In the original calculator, getop calls ungetch once: when it reads a non-digit character to terminate a number, it pushes that character back so the next call to getop will see it. The fix: instead of pushing back, store the lookahead character in a static local variable lastc, initialized to EOF. At the start of each call, check lastc first. This is the same technique as a single-character pushback buffer, but it lives inside getop itself — no shared state with getch.
Solution
/* K&R Exercise 4-11 — getop without ungetch, using a static variable
* Compile: gcc -ansi -Wall ex4-11.c -o ex4-11 */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define MAXOP 100
#define NUMBER '0'
#define MAXVAL 100
static double val[MAXVAL];
static int sp = 0;
void push(double f) { if (sp < MAXVAL) val[sp++] = f; }
double pop(void) { return sp > 0 ? val[--sp] : 0.0; }
/* No getch/ungetch needed */
int getop(char s[])
{
static int lastc = EOF; /* character read ahead but not yet consumed */
int i, c;
/* Use the saved character if there is one; otherwise read from stdin */
c = (lastc != EOF) ? lastc : getchar();
lastc = EOF;
/* skip leading whitespace */
while (c == ' ' || c == '\t')
c = getchar();
s[0] = c;
s[1] = '\0';
if (!isdigit(c) && c != '.')
return c;
i = 0;
if (isdigit(c))
while (isdigit(s[++i] = c = getchar()))
;
if (c == '.')
while (isdigit(s[++i] = c = getchar()))
;
s[i] = '\0';
if (c != EOF)
lastc = c; /* save the lookahead instead of calling ungetch */
return NUMBER;
}
int main(void)
{
int type;
double op2;
char s[MAXOP];
while ((type = getop(s)) != EOF) {
switch (type) {
case NUMBER: push(atof(s)); break;
case '+': push(pop() + pop()); break;
case '*': push(pop() * pop()); break;
case '-': op2 = pop(); push(pop() - op2); break;
case '/': op2 = pop(); if (pop()) push(pop()/op2); break;
case '\n': printf("\t%.8g\n", pop()); break;
}
}
return 0;
}
Compile and Test
gcc -ansi -Wall ex4-11.c -o ex4-11
echo "2 3 + 4 *" | ./ex4-11 # 20
Sample Output
20
What This Exercise Teaches
staticlocals as private state — astaticlocal variable persists across calls to the same function; it’s the simplest form of encapsulated state in C- Internalizing a dependency — moving the pushback from a shared module (
ungetch) to insidegetopreduces coupling;getopnow has no external dependencies beyondgetchar - Same invariant, different mechanism — whether you use
ungetchor astatic lastc, the invariant is identical: one character of lookahead is saved and returned at the start of the next call
Set Up Your C Environment
← Exercise 4-10 |
Chapter 4 Solutions |
Exercise 4-12 →
Book: The C Programming Language, 2nd Ed — Kernighan & Ritchie
1 comment on “K&R C Programs Exercise 4-11”