I have been reading through the C programming Langauge book and in section 4.3 I am trying to compile and run the code thats provided in pages 76-79. I think I have done exactly what is in the textbook, but its not working as it should.
From some printf's i have found that the numbers that are inputted are not actually being pushed to the stack in val[sp]
. instead, when printing out the number, it shows a 0
.
Also, the spaces aren't being skipped in
while((s[0] = c = getch()) == ' ' || c == '\t'{
;
}
and so the getop()
treats them as a non digit and just returns the space. Because of this the output just prints error unknown command
when the spaces are being read.
Also, the '+' is not being read as a command! So it just returns error unknown command
when the program encounters it. I am at a loss as how this is happening given I have copied word for word in the textbook and ran it. I am not sure if this code is out of date and doesn't run on newer machines as well. I am also using CodeBlocks to run this if that helps.
Any help is greatly appreciated!
Here's my code
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#define MAXOP 100
#define NUMBER '0'
int getop(char[]);
void push(double);
double pop(void);
int main()
{
//extern double val[MAXVAL];
int type;
double op2;
char s[MAXOP];
while((type = getop(s)) != EOF){
switch(type){
case NUMBER:
puts("a 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(op2 != 0.0){
push(pop() / op2);
}
else{
printf("error: zero division");
}
break;
case '\n':
printf("\t%.8g\n", pop());
break;
default:
printf("error unknown command %s\n", s);
break;
}
}
printf("Hello world!\n");
return 0;
}
#define MAXVAL 100
int sp = 0;
double val[MAXVAL];
void push(double f)
{
//extern int sp;
//extern double val[MAXVAL];
if(sp < MAXVAL){
val[++sp] = f;
}
else{
printf("stack full, can't push\n");
}
}
double pop(void)
{
//extern int sp;
//extern double val[MAXVAL];
if(sp > 0){
return val[--sp];
}
else{
printf("stack is empty\n");
return 0.0;
}
}
int getch(void);
void ungetch(int c);
int getop(char s[])
{
int i, c;
while((s[0] = c = getch()) == ' ' || c == '\t'){
;
}
s[1] = '\0';
if(!isdigit(c) && c != '.'){
printf("%c", c);
return c;
}
i = 0;
if(isdigit(c)){
while(isdigit(s[i++] = c = getch())){
;
}
}
if(c == '.'){
while(isdigit(s[i++] = c = getch())){
;
}
}
s[i] = '\0';
if(c != EOF){
ungetch(c);
}
return NUMBER;
}
#define BUFSIZE 100
char buf[BUFSIZE];
int bufp = 0;
int getch(void)
{
//extern int bufp;
//extern char buf[BUFSIZE];
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int c)
{
//extern int bufp;
//extern char buf[BUFSIZE];
if(bufp >= BUFSIZE){
printf("ungetch: too many characters\n");
}
else{
buf[++bufp] = c;
}
}
and the output for 3 4 +
1
I have tried to print out each part (the number when it is being pushed) and also print out the '+' to see if it is actually being returned as '+'. It is, and I am at a loss as how this is happening.
One problem is that your code has:
void ungetch(int c)
{
//extern int bufp;
//extern char buf[BUFSIZE];
if(bufp >= BUFSIZE){
printf("ungetch: too many characters\n");
}
else{
buf[++bufp] = c;
}
}
The book (p79) has:
void ungetch(int c)
{
if(bufp >= BUFSIZE){
printf("ungetch: too many characters\n");
}
else{
buf[bufp++] = c;
}
}
The difference between ++bufp
and bufp++
is critical.
It isn't the only problem, but things are closer to working when that's fixed.
You are consistently rewriting ++x
as x++
and x++
as ++x
, and the expressions are not interchangeable. It is very, very important to get those correct.
As pointed out by Oka, in the getop()
function, you have (twice):
while(isdigit(s[i++] = c = getch())){
;
}
where the book has:
while (isdigit(s[++i] = c = getch()))
;
In the push()
function, you have:
val[++sp] = f;
where the book has:
val[sp++] = f;
It is crucial that:
++x
and x++
.With those extra fixes — meaning changing your code to match what's in the book — the code seems to work, at least on the input 3 4 +
.