diff options
| author | Sadeep Madurange <smadurange@users.noreply.github.com> | 2021-12-08 18:34:01 +0800 |
|---|---|---|
| committer | Sadeep Madurange <smadurange@users.noreply.github.com> | 2021-12-08 18:34:01 +0800 |
| commit | 6a1918ac8fd0c54a4f81479370e474ccebd56f22 (patch) | |
| tree | 2e08f56789c84238010f6fb20bf65f03189cf792 /4/4.c | |
| parent | 189455cc86dc92b240034ac610f1ff9d10c01875 (diff) | |
| download | k&r-exercises-6a1918ac8fd0c54a4f81479370e474ccebd56f22.tar.gz | |
4.4
Diffstat (limited to '4/4.c')
| -rw-r--r-- | 4/4.c | 143 |
1 files changed, 143 insertions, 0 deletions
@@ -0,0 +1,143 @@ +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> + +#define MAXOP 100 /* max size of operand or operator */ +#define NUMBER '0' /* signal that a number was found */ +#define MAXVAL 100 /* max depth of val stack */ +#define BUFSIZE 100 + +// commands: +, -, *, /, %, p (prints the top one) +// c (dups top), s (swaps top two), c (clear stack) + +int sp = 0; /* next free stack position */ +double val[MAXVAL]; /* value stack */ + +int bufp = 0; /* next free position in buf */ +char buf[BUFSIZE]; /* buffer for ungetch */ + +/* get next operator or numeric operand */ +int getop(char[]); + +/* push f onto value stack */ +void push(double); + +/* pop and return top value from stack */ +double pop(); + +/* returns a value from stack without removing it */ +double peek(); + +/* reverse Polish calculator with support for modulus operator and negative + * numbers */ +int main(int argc, char *argv[]) { + 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: division by zero\n"); + break; + case '%': + op2 = pop(); + if (op2 != 0.0) + push((int)pop() % (int)op2); + else + printf("error: division by zero\n"); + break; + case 'p': + peek(); + break; + case '\n': + printf("\t%.8g\n", pop()); + break; + default: + printf("error: unknown command %s\n", s); + } + } + + return 0; +} + +void push(double f) { + if (sp < MAXVAL) + val[sp++] = f; + else + printf("error: stack empty\n"); +} + +double pop() { + if (sp > 0) + return val[--sp]; + else { + printf("error: stack empty\n"); + return 0.0; + } +} + +double peek() { + if (sp > 0) + return val[sp]; + else { + printf("error: stack empty\n"); + return 0.0; + } +} + +int getch() { + return (bufp > 0) ? buf[--bufp] : getchar(); +} + +void ungetch(int c) { + if (bufp >= BUFSIZE) + printf("ungetch: too many characters\n"); + else + buf[bufp++] = c; +} + +int getop(char s[]) { + int i, c; + + while ((s[0] = c = getch()) == ' ' || c == '\t') + ; + s[1] = 0; + + if (!isdigit(c) && c != '.' && c != '-') + return c; + + i = 0; + if (isdigit(c)) + while (isdigit(s[++i] = c = getch())) + ; + if (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; +} |
