I've been following the K&R C book and I'm confused with one part of the given code for the reverse polish calculator in section 4.3.
There's an if
statement at the bottom of the getop
function
/* getop: get next operator or numeric operand */
int getop(char s[])
{
int i, c;
while ((s[0] = c = getch()) == ' ' || c == '\t')
;
s[1] = '\0';
if (!isdigit(c) && c != '.')
return c; /* not a number */
i = 0;
if (isdigit(c)) /* collect integer part */
while (isdigit(s[++i] = c = getch()))
;
if (c == '.') /* collect fractional part */
while (isdigit(s[++i] = c = getch()))
;
s[i] = '\0';
if (c != EOF)
ungetch(c);
return NUMBER;
}
which (other than when c == EOF
) puts the last character onto the getch
/ungetch
buffer, because it will need to be read when we get the next operator/operand.
But if we have EOF
, then it is not put onto the buffer (rightly so, since the buffer only takes char
s and EOF
may not be a char
since it it implementation-dependent whether char
s are signed or unsigned), so when we go through getop
the next time, when the first getch
function happens it will not pick up the EOF
from the previous going-through of getop
. Therefore the EOF
won't be returned by getop
.
This seems like incorrect behaviour (by my reasoning), since the condition to keep running the calculator depends on not getting an EOF
returned by getop
(that is, when we reach the end of the file, we should stop running the program), but it seems that an EOF
immediately after a digit character will slip through, undetected.
What am I understanding incorrectly (I expect it has something to do with how EOF
works)?
I tried to think about what would happen in a concrete example, say where we have
1EOF2+\nEOF
as input to the calculator.
The expected behaviour is that 1
is printed and the calculator stops running.
My reasoning says that
s[i] = '\0';
line, where we overwrite s[1]
(which was EOF
) with \0
, so s
is the string "1"
.if(c != EOF)
condition with c == EOF
. We return NUMBER
and 1
is successfully pushed to the stack.getop
.getch
function and get the next character, '2'
, since the getch
/ungetch
buffer is empty because we didn't ungetch
EOF
.2
to the stack.getop
returns '+'
, so we pop 1
and 2
and push 3
.\n
so we print 3
.EOF
so we stop running the calculator.This seems like the wrong behaviour. What am I getting wrong?
EOF
is not a character and it is not stored in the buffer. It is a state of stream or file.
So every time you try to read the file/stream you will get EOF
.
1EOF2+\nEOF
is a nonsense as EOF
is not in a buffer.