2 5dc21454 2023-07-14 jrmu * Exercise 4-10. An alternative organization uses getline to read an entire
3 5dc21454 2023-07-14 jrmu * input line; this makes getch and ungetch unnecessary. Revise the calculator
4 5dc21454 2023-07-14 jrmu * to use this approach.
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 #include <math.h> /* for math functions */
10 5dc21454 2023-07-14 jrmu #include <string.h> /* for strcmp() */
12 5dc21454 2023-07-14 jrmu #define MAXOP 100 /* max size of operand or operator */
13 5dc21454 2023-07-14 jrmu #define NUMBER '0' /* signal that a number was found */
14 5dc21454 2023-07-14 jrmu #define IDENTIFIER '1' /* signal that an identifier was found */
15 5dc21454 2023-07-14 jrmu #define VARIABLE '2' /* signal that a variable was found */
16 5dc21454 2023-07-14 jrmu #define ASSIGNMENT '3' /* signal that a variable was found */
17 5dc21454 2023-07-14 jrmu #define LETTERS 26 /* number of letters in alphabet */
19 5dc21454 2023-07-14 jrmu int getop(char []);
20 5dc21454 2023-07-14 jrmu void push(double);
21 5dc21454 2023-07-14 jrmu double pop(void);
22 5dc21454 2023-07-14 jrmu double printtop(void);
23 5dc21454 2023-07-14 jrmu int duplicate(void);
24 5dc21454 2023-07-14 jrmu int swap(void);
25 5dc21454 2023-07-14 jrmu void clear(void);
26 5dc21454 2023-07-14 jrmu int assign(char, double);
27 5dc21454 2023-07-14 jrmu double interpolate(char);
29 5dc21454 2023-07-14 jrmu /* reverse Polish calculator */
30 5dc21454 2023-07-14 jrmu int main() {
32 5dc21454 2023-07-14 jrmu double op2, val;
33 5dc21454 2023-07-14 jrmu char s[MAXOP];
35 5dc21454 2023-07-14 jrmu while ((type = getop(s)) != EOF) {
36 5dc21454 2023-07-14 jrmu switch (type) {
37 5dc21454 2023-07-14 jrmu case NUMBER:
38 5dc21454 2023-07-14 jrmu push(atof(s));
40 5dc21454 2023-07-14 jrmu case IDENTIFIER:
41 5dc21454 2023-07-14 jrmu if (strcmp(s, "sin") == 0)
42 5dc21454 2023-07-14 jrmu push(sin(pop()));
43 5dc21454 2023-07-14 jrmu else if (strcmp(s, "cos") == 0)
44 5dc21454 2023-07-14 jrmu push(cos(pop()));
45 5dc21454 2023-07-14 jrmu else if (strcmp(s, "exp") == 0)
46 5dc21454 2023-07-14 jrmu push(exp(pop()));
48 5dc21454 2023-07-14 jrmu case VARIABLE:
49 5dc21454 2023-07-14 jrmu push(interpolate(s[0]));
51 5dc21454 2023-07-14 jrmu case ASSIGNMENT:
52 5dc21454 2023-07-14 jrmu assign(s[0], atof(s+2));
55 5dc21454 2023-07-14 jrmu push(pop() + pop());
58 5dc21454 2023-07-14 jrmu push(pop() * pop());
61 5dc21454 2023-07-14 jrmu op2 = pop();
62 5dc21454 2023-07-14 jrmu push(pop() - op2);
65 5dc21454 2023-07-14 jrmu op2 = pop();
66 5dc21454 2023-07-14 jrmu if (op2 != 0.0)
67 5dc21454 2023-07-14 jrmu push(pop() / op2);
69 5dc21454 2023-07-14 jrmu printf("error: zero divisor\n");
72 5dc21454 2023-07-14 jrmu op2 = pop();
73 5dc21454 2023-07-14 jrmu if (op2 != 0.0)
74 5dc21454 2023-07-14 jrmu push((int) pop() % (int) op2);
76 5dc21454 2023-07-14 jrmu printf("error: zero divisor\n");
79 5dc21454 2023-07-14 jrmu printf("\t%.8g\n", printtop());
82 5dc21454 2023-07-14 jrmu if (duplicate() == 0)
83 5dc21454 2023-07-14 jrmu printf("error: can't duplicate\n");
86 5dc21454 2023-07-14 jrmu if (swap() == 0)
87 5dc21454 2023-07-14 jrmu printf("error: swap failed, stack needs two numbers\n");
93 5dc21454 2023-07-14 jrmu printf("\t%.8g\n", pop());
96 5dc21454 2023-07-14 jrmu printf("error: unknown command %s\n", s);
102 5dc21454 2023-07-14 jrmu #include <ctype.h> /* for tolower() */
103 5dc21454 2023-07-14 jrmu #define MAXVAL 100 /* maximum depth of val stack */
105 5dc21454 2023-07-14 jrmu int sp = 0; /* next free stack position */
106 5dc21454 2023-07-14 jrmu double val[MAXVAL]; /* value stack */
107 5dc21454 2023-07-14 jrmu double var[LETTERS]; /* variable stack */
109 5dc21454 2023-07-14 jrmu /* push: push f onto value stack */
110 5dc21454 2023-07-14 jrmu void push (double f) {
111 5dc21454 2023-07-14 jrmu if (sp < MAXVAL)
112 5dc21454 2023-07-14 jrmu val[sp++] = f;
114 5dc21454 2023-07-14 jrmu printf ("error: stack full, can't push %g\n", f);
117 5dc21454 2023-07-14 jrmu /* pop: pop and return top value from stack */
118 5dc21454 2023-07-14 jrmu double pop(void) {
119 5dc21454 2023-07-14 jrmu if (sp > 0)
120 5dc21454 2023-07-14 jrmu return val[--sp];
122 5dc21454 2023-07-14 jrmu printf("error: stack empty\n");
123 5dc21454 2023-07-14 jrmu return 0.0;
127 5dc21454 2023-07-14 jrmu /* printtop: print the top value of the stack without popping it */
128 5dc21454 2023-07-14 jrmu double printtop(void) {
129 5dc21454 2023-07-14 jrmu if (sp > 0)
130 5dc21454 2023-07-14 jrmu return val[sp-1];
132 5dc21454 2023-07-14 jrmu printf("error: stack empty\n");
133 5dc21454 2023-07-14 jrmu return 0.0;
137 5dc21454 2023-07-14 jrmu /* duplicate: duplicate the top value of the stack
138 5dc21454 2023-07-14 jrmu * return 1 if successful, 0 on failure */
139 5dc21454 2023-07-14 jrmu int duplicate(void) {
140 5dc21454 2023-07-14 jrmu if (sp <= 0) {
142 5dc21454 2023-07-14 jrmu } else if (sp >= MAXVAL) {
145 5dc21454 2023-07-14 jrmu val[sp] = val[sp-1];
151 5dc21454 2023-07-14 jrmu /* swap: swap the top two values of the stack
152 5dc21454 2023-07-14 jrmu * return 1 if successful, 0 on failure */
153 5dc21454 2023-07-14 jrmu int swap(void) {
154 5dc21454 2023-07-14 jrmu if (sp > 1) {
155 5dc21454 2023-07-14 jrmu int temp = val[sp-1];
156 5dc21454 2023-07-14 jrmu val[sp-1] = val[sp-2];
157 5dc21454 2023-07-14 jrmu val[sp-2] = temp;
163 5dc21454 2023-07-14 jrmu /* clear: clear the stack */
164 5dc21454 2023-07-14 jrmu void clear(void) {
168 5dc21454 2023-07-14 jrmu /* assign: assign a double to a variable
169 5dc21454 2023-07-14 jrmu * return 1 on success, 0 on failure */
170 5dc21454 2023-07-14 jrmu int assign(char variable, double value) {
171 5dc21454 2023-07-14 jrmu int index = tolower(variable) - 'a';
172 5dc21454 2023-07-14 jrmu if (0 <= index && index < LETTERS) {
173 5dc21454 2023-07-14 jrmu var[index] = value;
176 5dc21454 2023-07-14 jrmu printf("error: assignment failed, variable needs to be single letter\n");
180 5dc21454 2023-07-14 jrmu /* interpolate: interpolate variable */
181 5dc21454 2023-07-14 jrmu double interpolate(char variable) {
182 5dc21454 2023-07-14 jrmu int index = tolower(variable) - 'a';
183 5dc21454 2023-07-14 jrmu if (0 <= index && index < LETTERS) {
184 5dc21454 2023-07-14 jrmu return var[index];
186 5dc21454 2023-07-14 jrmu printf("error: variable must be single letter\n");
187 5dc21454 2023-07-14 jrmu return 0.0;
190 5dc21454 2023-07-14 jrmu #include <ctype.h>
192 5dc21454 2023-07-14 jrmu /* getlin: get line into s, return length */
193 5dc21454 2023-07-14 jrmu int getlin(char s[], int lim) {
196 5dc21454 2023-07-14 jrmu while (--lim > 0 && (c=getchar()) != EOF && c != '\n')
197 5dc21454 2023-07-14 jrmu s[i++] = c;
198 5dc21454 2023-07-14 jrmu if (c == '\n' || c == EOF)
199 5dc21454 2023-07-14 jrmu s[i++] = c;
200 5dc21454 2023-07-14 jrmu s[i] = '\0';
204 5dc21454 2023-07-14 jrmu char buf[MAXOP] = "\n"; /* buffer for current line */
205 5dc21454 2023-07-14 jrmu int bufp = 0; /* next char to scan in buffer */
207 5dc21454 2023-07-14 jrmu /* getop: get next operator or numeric operand */
208 5dc21454 2023-07-14 jrmu int getop(char s[]) {
210 5dc21454 2023-07-14 jrmu while ((s[0] = c = buf[bufp++]) == ' ' || c == '\t')
212 5dc21454 2023-07-14 jrmu s[1] = '\0';
214 5dc21454 2023-07-14 jrmu if (isalpha(c)) {
215 5dc21454 2023-07-14 jrmu while ((s[++i] = c = buf[bufp++]) != ' ' && c != '\t' && c != '\n')
217 5dc21454 2023-07-14 jrmu s[i] = '\0';
218 5dc21454 2023-07-14 jrmu if (c != EOF)
220 5dc21454 2023-07-14 jrmu if (s[1] == '=') {
221 5dc21454 2023-07-14 jrmu return ASSIGNMENT;
222 5dc21454 2023-07-14 jrmu } else if (s[1] == '\0') {
223 5dc21454 2023-07-14 jrmu return VARIABLE;
225 5dc21454 2023-07-14 jrmu return IDENTIFIER;
228 5dc21454 2023-07-14 jrmu /* negative number or minus */
229 5dc21454 2023-07-14 jrmu if (c == '-') {
230 5dc21454 2023-07-14 jrmu s[++i] = c = buf[bufp++];
231 5dc21454 2023-07-14 jrmu if (!isdigit(c) && c != '.') {
233 5dc21454 2023-07-14 jrmu return '-';
236 5dc21454 2023-07-14 jrmu if (c == '\n') {
237 5dc21454 2023-07-14 jrmu getlin(buf, MAXOP);
240 5dc21454 2023-07-14 jrmu if (!isdigit(c) && c != '.')
241 5dc21454 2023-07-14 jrmu return c; /* not a number */
242 5dc21454 2023-07-14 jrmu if (isdigit(c)) /* collect integer part */
243 5dc21454 2023-07-14 jrmu while (isdigit(s[++i] = c = buf[bufp++]))
245 5dc21454 2023-07-14 jrmu if (c == '.') /* collect fraction part */
246 5dc21454 2023-07-14 jrmu while (isdigit(s[++i] = c = buf[bufp++]))
248 5dc21454 2023-07-14 jrmu s[i] = '\0';
249 5dc21454 2023-07-14 jrmu if (c != EOF)
251 5dc21454 2023-07-14 jrmu return NUMBER;