Blob


1 /*
2 * Exercise 4-11. Modify getop so that it doesn't need to use ungetch. Hint:
3 * use an internal static variable.
4 */
6 #include <stdio.h>
7 #include <stdlib.h> /* for atof() */
8 #include <math.h> /* for math functions */
9 #include <string.h> /* for strcmp() */
10 #include <ctype.h> /* for tolower() */
12 #define MAXOP 100 /* max size of operand or operator */
13 #define NUMBER '0' /* signal that a number was found */
14 #define IDENTIFIER '1' /* signal that an identifier was found */
15 #define VARIABLE '2' /* signal that a variable was found */
16 #define ASSIGNMENT '3' /* signal that a variable was found */
17 #define LETTERS 26 /* number of letters in alphabet */
19 int getop(char []);
20 void push(double);
21 double pop(void);
22 double printtop(void);
23 int duplicate(void);
24 int swap(void);
25 void clear(void);
26 int assign(int, double);
27 double eval(int index);
29 /* reverse Polish calculator */
30 int main() {
31 int type;
32 double op2, val;
33 char s[MAXOP];
34 int index;
35 while ((type = getop(s)) != EOF) {
36 switch (type) {
37 case NUMBER:
38 push(atof(s));
39 break;
40 case IDENTIFIER:
41 if (strcmp(s, "sin") == 0)
42 push(sin(pop()));
43 else if (strcmp(s, "cos") == 0)
44 push(cos(pop()));
45 else if (strcmp(s, "exp") == 0)
46 push(exp(pop()));
47 break;
48 case VARIABLE:
49 index = tolower(s[0]) - 'a';
50 if (0 <= index && index < LETTERS) {
51 push(eval(index));
52 } else {
53 printf("error: variable must be single letter\n");
54 }
55 break;
56 case ASSIGNMENT:
57 index = tolower(s[0]) - 'a';
58 val = atof(s+2);
59 if (!assign(index, val)) {
60 printf("error: assignment failed, variable needs to be single letter\n");
61 }
62 break;
63 case '+':
64 push(pop() + pop());
65 break;
66 case '*':
67 push(pop() * pop());
68 break;
69 case '-':
70 op2 = pop();
71 push(pop() - op2);
72 break;
73 case '/':
74 op2 = pop();
75 if (op2 != 0.0)
76 push(pop() / op2);
77 else
78 printf("error: zero divisor\n");
79 break;
80 case '%':
81 op2 = pop();
82 if (op2 != 0.0)
83 push((int) pop() % (int) op2);
84 else
85 printf("error: zero divisor\n");
86 break;
87 case '?':
88 printf("\t%.8g\n", printtop());
89 break;
90 case '#':
91 if (duplicate() == 0)
92 printf("error: can't duplicate\n");
93 break;
94 case '~':
95 if (swap() == 0)
96 printf("error: swap failed, stack needs two numbers\n");
97 break;
98 case '!':
99 clear();
100 break;
101 case '\n':
102 printf("\t%.8g\n", pop());
103 break;
104 default:
105 printf("error: unknown command %s\n", s);
106 break;
111 #define MAXVAL 100 /* maximum depth of val stack */
113 int sp = 0; /* next free stack position */
114 double val[MAXVAL]; /* value stack */
115 double var[LETTERS]; /* variable stack */
117 /* push: push f onto value stack */
118 void push (double f) {
119 if (sp < MAXVAL)
120 val[sp++] = f;
121 else
122 printf ("error: stack full, can't push %g\n", f);
125 /* pop: pop and return top value from stack */
126 double pop(void) {
127 if (sp > 0)
128 return val[--sp];
129 else {
130 printf("error: stack empty\n");
131 return 0.0;
135 /* printtop: print the top value of the stack without popping it */
136 double printtop(void) {
137 if (sp > 0)
138 return val[sp-1];
139 else {
140 printf("error: stack empty\n");
141 return 0.0;
145 /* duplicate: duplicate the top value of the stack
146 * return 1 if successful, 0 on failure */
147 int duplicate(void) {
148 if (sp <= 0) {
149 return 0;
150 } else if (sp >= MAXVAL) {
151 return 0;
152 } else {
153 val[sp] = val[sp-1];
154 sp++;
155 return 1;
159 /* swap: swap the top two values of the stack
160 * return 1 if successful, 0 on failure */
161 int swap(void) {
162 if (sp > 1) {
163 int temp = val[sp-1];
164 val[sp-1] = val[sp-2];
165 val[sp-2] = temp;
166 return 1;
168 return 0;
171 /* clear: clear the stack */
172 void clear(void) {
173 sp = 0;
176 /* assign: assign a double to a variable, letters represented by int from 0-25
177 * return 1 on success, 0 on failure */
178 int assign(int index, double value) {
179 if (0 <= index && index < LETTERS) {
180 var[index] = value;
181 return 1;
183 return 0;
186 /* eval: evaluate variable, letters represented by int from 0-25 */
187 double eval(int index) {
188 if (0 <= index && index < LETTERS) {
189 return var[index];
191 return 0.0;
194 #include <ctype.h>
196 int getch(void);
197 void ungetch(int);
199 /* getop: get next operator or numeric operand */
200 int getop(char s[]) {
201 int i;
202 static int c = ' ';
203 int op;
204 while (c == ' ' || c == '\t') {
205 c = getchar();
207 s[0] = c;
208 s[1] = '\0';
209 i = 0;
210 if (isalpha(c)) {
211 while ((s[++i] = c = getch()) != ' ' && c != '\t' && c != '\n')
213 s[i] = '\0';
214 if (s[1] == '=') {
215 return ASSIGNMENT;
216 } else if (s[1] == '\0') {
217 return VARIABLE;
218 } else {
219 return IDENTIFIER;
222 /* negative number or minus */
223 if (c == '-') {
224 s[++i] = c = getch();
225 if (!isdigit(c) && c != '.') {
226 return '-';
229 if (!isdigit(c) && c != '.') {
230 op = c;
231 c = ' ';
232 return op; /* not a number */
234 if (isdigit(c)) /* collect integer part */
235 while (isdigit(s[++i] = c = getch()))
237 if (c == '.') /* collect fraction part */
238 while (isdigit(s[++i] = c = getch()))
240 s[i] = '\0';
241 return NUMBER;
244 #define BUFSIZE 100
246 char buf[BUFSIZE]; /* buffer for ungetch */
247 int bufp = 0;
249 /* get a (possibly pushed back) character */
250 int getch(void) {
251 return (bufp > 0) ? buf[--bufp] : getchar();
254 /* push character back on input */
255 void ungetch(int c) {
256 if (bufp >= BUFSIZE)
257 printf("ungetch: too many characters\n");
258 else
259 buf[bufp++] = c;