Blame


1 5dc21454 2023-07-14 jrmu /*
2 5dc21454 2023-07-14 jrmu * Exercise 4-3. Given the basic framework, it's straightforward to extend the
3 5dc21454 2023-07-14 jrmu * calculator. Add the modulus (%) operator and provisions for negative
4 5dc21454 2023-07-14 jrmu * numbers.
5 5dc21454 2023-07-14 jrmu */
6 5dc21454 2023-07-14 jrmu
7 5dc21454 2023-07-14 jrmu #include <stdio.h>
8 5dc21454 2023-07-14 jrmu #include <stdlib.h> /* for atof() */
9 5dc21454 2023-07-14 jrmu
10 5dc21454 2023-07-14 jrmu #define MAXOP 100 /* max size of operand or operator */
11 5dc21454 2023-07-14 jrmu #define NUMBER '0' /* signal that a number was found */
12 5dc21454 2023-07-14 jrmu
13 5dc21454 2023-07-14 jrmu int getop(char []);
14 5dc21454 2023-07-14 jrmu void push(double);
15 5dc21454 2023-07-14 jrmu double pop(void);
16 5dc21454 2023-07-14 jrmu
17 5dc21454 2023-07-14 jrmu /* reverse Polish calculator */
18 5dc21454 2023-07-14 jrmu int main() {
19 5dc21454 2023-07-14 jrmu int type;
20 5dc21454 2023-07-14 jrmu double op2;
21 5dc21454 2023-07-14 jrmu char s[MAXOP];
22 5dc21454 2023-07-14 jrmu
23 5dc21454 2023-07-14 jrmu while ((type = getop(s)) != EOF) {
24 5dc21454 2023-07-14 jrmu switch (type) {
25 5dc21454 2023-07-14 jrmu case NUMBER:
26 5dc21454 2023-07-14 jrmu push(atof(s));
27 5dc21454 2023-07-14 jrmu break;
28 5dc21454 2023-07-14 jrmu case '+':
29 5dc21454 2023-07-14 jrmu push(pop() + pop());
30 5dc21454 2023-07-14 jrmu break;
31 5dc21454 2023-07-14 jrmu case '*':
32 5dc21454 2023-07-14 jrmu push(pop() * pop());
33 5dc21454 2023-07-14 jrmu break;
34 5dc21454 2023-07-14 jrmu case '-':
35 5dc21454 2023-07-14 jrmu op2 = pop();
36 5dc21454 2023-07-14 jrmu push(pop() - op2);
37 5dc21454 2023-07-14 jrmu break;
38 5dc21454 2023-07-14 jrmu case '/':
39 5dc21454 2023-07-14 jrmu op2 = pop();
40 5dc21454 2023-07-14 jrmu if (op2 != 0.0)
41 5dc21454 2023-07-14 jrmu push(pop() / op2);
42 5dc21454 2023-07-14 jrmu else
43 5dc21454 2023-07-14 jrmu printf("error: zero divisor\n");
44 5dc21454 2023-07-14 jrmu break;
45 5dc21454 2023-07-14 jrmu case '%':
46 5dc21454 2023-07-14 jrmu op2 = pop();
47 5dc21454 2023-07-14 jrmu if (op2 != 0.0)
48 5dc21454 2023-07-14 jrmu push((int) pop() % (int) op2);
49 5dc21454 2023-07-14 jrmu else
50 5dc21454 2023-07-14 jrmu printf("error: zero divisor\n");
51 5dc21454 2023-07-14 jrmu break;
52 5dc21454 2023-07-14 jrmu case '\n':
53 5dc21454 2023-07-14 jrmu printf("\t%.8g\n", pop());
54 5dc21454 2023-07-14 jrmu break;
55 5dc21454 2023-07-14 jrmu default:
56 5dc21454 2023-07-14 jrmu printf("error: unknown command %s\n", s);
57 5dc21454 2023-07-14 jrmu break;
58 5dc21454 2023-07-14 jrmu }
59 5dc21454 2023-07-14 jrmu }
60 5dc21454 2023-07-14 jrmu }
61 5dc21454 2023-07-14 jrmu
62 5dc21454 2023-07-14 jrmu #define MAXVAL 100 /* maximum depth of val stack */
63 5dc21454 2023-07-14 jrmu
64 5dc21454 2023-07-14 jrmu int sp = 0; /* next free stack position */
65 5dc21454 2023-07-14 jrmu double val[MAXVAL]; /* value stack */
66 5dc21454 2023-07-14 jrmu
67 5dc21454 2023-07-14 jrmu /* push: push f onto value stack */
68 5dc21454 2023-07-14 jrmu void push (double f) {
69 5dc21454 2023-07-14 jrmu if (sp < MAXVAL)
70 5dc21454 2023-07-14 jrmu val[sp++] = f;
71 5dc21454 2023-07-14 jrmu else
72 5dc21454 2023-07-14 jrmu printf ("error: stack full, can't push %g\n", f);
73 5dc21454 2023-07-14 jrmu }
74 5dc21454 2023-07-14 jrmu
75 5dc21454 2023-07-14 jrmu /* pop: pop and return top value from stack */
76 5dc21454 2023-07-14 jrmu double pop(void) {
77 5dc21454 2023-07-14 jrmu if (sp > 0)
78 5dc21454 2023-07-14 jrmu return val[--sp];
79 5dc21454 2023-07-14 jrmu else {
80 5dc21454 2023-07-14 jrmu printf("error: stack empty\n");
81 5dc21454 2023-07-14 jrmu return 0.0;
82 5dc21454 2023-07-14 jrmu }
83 5dc21454 2023-07-14 jrmu }
84 5dc21454 2023-07-14 jrmu
85 5dc21454 2023-07-14 jrmu #include <ctype.h>
86 5dc21454 2023-07-14 jrmu
87 5dc21454 2023-07-14 jrmu int getch(void);
88 5dc21454 2023-07-14 jrmu void ungetch(int);
89 5dc21454 2023-07-14 jrmu
90 5dc21454 2023-07-14 jrmu /* getop: get next operator or numeric operand */
91 5dc21454 2023-07-14 jrmu int getop(char s[]) {
92 5dc21454 2023-07-14 jrmu int i, c;
93 5dc21454 2023-07-14 jrmu while ((s[0] = c = getch()) == ' ' || c == '\t')
94 5dc21454 2023-07-14 jrmu ;
95 5dc21454 2023-07-14 jrmu s[1] = '\0';
96 5dc21454 2023-07-14 jrmu i = 0;
97 5dc21454 2023-07-14 jrmu /* negative number or minus */
98 5dc21454 2023-07-14 jrmu if (c == '-') {
99 5dc21454 2023-07-14 jrmu s[++i] = c = getch();
100 5dc21454 2023-07-14 jrmu if (!isdigit(c) && c != '.') {
101 5dc21454 2023-07-14 jrmu ungetch(c);
102 5dc21454 2023-07-14 jrmu return '-';
103 5dc21454 2023-07-14 jrmu }
104 5dc21454 2023-07-14 jrmu }
105 5dc21454 2023-07-14 jrmu if (!isdigit(c) && c != '.')
106 5dc21454 2023-07-14 jrmu return c; /* not a number */
107 5dc21454 2023-07-14 jrmu if (isdigit(c)) /* collect integer part */
108 5dc21454 2023-07-14 jrmu while (isdigit(s[++i] = c = getch()))
109 5dc21454 2023-07-14 jrmu ;
110 5dc21454 2023-07-14 jrmu if (c == '.') /* collect fraction part */
111 5dc21454 2023-07-14 jrmu while (isdigit(s[++i] = c = getch()))
112 5dc21454 2023-07-14 jrmu ;
113 5dc21454 2023-07-14 jrmu s[i] = '\0';
114 5dc21454 2023-07-14 jrmu if (c != EOF)
115 5dc21454 2023-07-14 jrmu ungetch(c);
116 5dc21454 2023-07-14 jrmu return NUMBER;
117 5dc21454 2023-07-14 jrmu }
118 5dc21454 2023-07-14 jrmu
119 5dc21454 2023-07-14 jrmu #define BUFSIZE 100
120 5dc21454 2023-07-14 jrmu
121 5dc21454 2023-07-14 jrmu char buf[BUFSIZE]; /* buffer for ungetch */
122 5dc21454 2023-07-14 jrmu int bufp = 0;
123 5dc21454 2023-07-14 jrmu
124 5dc21454 2023-07-14 jrmu /* get a (possibly pushed back) character */
125 5dc21454 2023-07-14 jrmu int getch(void) {
126 5dc21454 2023-07-14 jrmu return (bufp > 0) ? buf[--bufp] : getchar();
127 5dc21454 2023-07-14 jrmu }
128 5dc21454 2023-07-14 jrmu
129 5dc21454 2023-07-14 jrmu /* push character back on input */
130 5dc21454 2023-07-14 jrmu void ungetch(int c) {
131 5dc21454 2023-07-14 jrmu if (bufp >= BUFSIZE)
132 5dc21454 2023-07-14 jrmu printf("ungetch: too many characters\n");
133 5dc21454 2023-07-14 jrmu else
134 5dc21454 2023-07-14 jrmu buf[bufp++] = c;
135 5dc21454 2023-07-14 jrmu }