#include #include #include #define NUMBER '0' #define MAXOP 100 #define MAXVAL 100 int getop(char[]); void push(double); double pop(void); // Naïve implementation of remainder operation double frem(double f1, double f2) { return f1 - (f2 * (int)(f1 / f2)); } /** * Reverse polish notation calculator */ 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 (op2 != 0.0) push(pop() / op2); else printf("error: zero division attempted!\n"); break; case '%': op2 = pop(); if (op2 != 0.0) push(frem(pop(), op2)); else printf("error: zero division attempted!\n"); break; case '\n': printf("\t%.8g\n", pop()); break; default: printf("unknown command %s\n", s); break; } } return 0; } int sp; // Stack position double val[MAXVAL]; // Value stack void push(double f) { if (sp < MAXVAL) { val[sp++] = f; } else { printf("error, stack full\n"); } } double pop(void) { if (sp >= 0) { return val[--sp]; } else { printf("error, empty stack\n"); return 0.0; } } int getch(void); void ungetch(int); int getop(char s[]) { int i,c; // Skip to teh first non-space or tab character while ((s[0] = c = getch()) == ' ' || c == '\t'); // Then add a null for some reason? s[1] = '\0'; // if it's not a part of a number, it's an operation if (!isdigit(c) && c != '.') return c; // Integer part i = 0; if (isdigit(c)) while (isdigit(s[++i] = c = getch())); // fraction part if (c == '.') while (isdigit(s[++i] = c = getch())); s[i] = '\0'; if (c != EOF) ungetch(c); return NUMBER; } #define BUFSIZE 100 char buf[BUFSIZE]; // buffer for ungetch int bufp = 0; // next free in buf int getch(void) { return (bufp > 0) ? buf[--bufp] : getchar(); } void ungetch(int c) { if (bufp >= BUFSIZE) printf("ungetch: buffer full\n"); else buf[bufp++] = c; }