Created
May 30, 2012 12:56
-
-
Save gsf/2836137 to your computer and use it in GitHub Desktop.
calc.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // from K&R section 4.3 | |
| #include <stdio.h> | |
| #include <stdlib.h> // for atof() | |
| #include <ctype.h> | |
| #define MAXOP 100 // max size of operand | |
| #define NUMBER '0' // signal that a number was found | |
| #define MAXVAL 100 // max depth of value stack | |
| #define BUFSIZE 100 | |
| int sp = 0; // next free stack position | |
| double val[MAXVAL]; // value stack | |
| char buf[BUFSIZE]; // buffer for ungetch | |
| int bufp = 0; // next free position in buffer | |
| // get a (possibly pushed back) character | |
| int getch(void){ | |
| return (bufp > 0) ? buf[--bufp] : getchar(); | |
| } | |
| // push character back on input | |
| void ungetch(int c) { | |
| if (bufp >= BUFSIZE) | |
| printf("ungetch: too many characters\n"); | |
| else | |
| buf[bufp++] = c; | |
| } | |
| // get next operator or 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 fraction part | |
| while (isdigit(s[++i] = c = getch())); | |
| s[i] = '\0'; | |
| if (c != EOF) | |
| ungetch(c); | |
| return NUMBER; | |
| } | |
| // push f onto value stack | |
| void push(double f) { | |
| if (sp < MAXVAL) | |
| val[sp++] = f; | |
| else | |
| printf("error: stack full, can't push %g\n", f); | |
| } | |
| // pop and return top value from stack | |
| double pop(void) { | |
| if (sp > 0) | |
| return val[--sp]; | |
| else { | |
| printf("error: stack empty\n"); | |
| return 0.0; | |
| } | |
| } | |
| // Reverse Polish calculator | |
| main() { | |
| 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 divisor\n"); | |
| break; | |
| case '\n': | |
| printf("\t%.8g\n", pop()); | |
| break; | |
| default: | |
| printf("error: unknown command %s\n", s); | |
| break; | |
| } | |
| } | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment