2 * Exercise 4-10. An alternative organization uses getline to read an entire
3 * input line; this makes getch and ungetch unnecessary. Revise the calculator
4 * to use this approach.
8 #include <stdlib.h> /* for atof() */
9 #include <math.h> /* for math functions */
10 #include <string.h> /* for strcmp() */
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 */
22 double printtop(void);
26 int assign(char, double);
27 double interpolate(char);
29 /* reverse Polish calculator */
35 while ((type = getop(s)) != EOF) {
41 if (strcmp(s, "sin") == 0)
43 else if (strcmp(s, "cos") == 0)
45 else if (strcmp(s, "exp") == 0)
49 push(interpolate(s[0]));
52 assign(s[0], atof(s+2));
69 printf("error: zero divisor\n");
74 push((int) pop() % (int) op2);
76 printf("error: zero divisor\n");
79 printf("\t%.8g\n", printtop());
83 printf("error: can't duplicate\n");
87 printf("error: swap failed, stack needs two numbers\n");
93 printf("\t%.8g\n", pop());
96 printf("error: unknown command %s\n", s);
102 #include <ctype.h> /* for tolower() */
103 #define MAXVAL 100 /* maximum depth of val stack */
105 int sp = 0; /* next free stack position */
106 double val[MAXVAL]; /* value stack */
107 double var[LETTERS]; /* variable stack */
109 /* push: push f onto value stack */
110 void push (double f) {
114 printf ("error: stack full, can't push %g\n", f);
117 /* pop: pop and return top value from stack */
122 printf("error: stack empty\n");
127 /* printtop: print the top value of the stack without popping it */
128 double printtop(void) {
132 printf("error: stack empty\n");
137 /* duplicate: duplicate the top value of the stack
138 * return 1 if successful, 0 on failure */
139 int duplicate(void) {
142 } else if (sp >= MAXVAL) {
151 /* swap: swap the top two values of the stack
152 * return 1 if successful, 0 on failure */
155 int temp = val[sp-1];
156 val[sp-1] = val[sp-2];
163 /* clear: clear the stack */
168 /* assign: assign a double to a variable
169 * return 1 on success, 0 on failure */
170 int assign(char variable, double value) {
171 int index = tolower(variable) - 'a';
172 if (0 <= index && index < LETTERS) {
176 printf("error: assignment failed, variable needs to be single letter\n");
180 /* interpolate: interpolate variable */
181 double interpolate(char variable) {
182 int index = tolower(variable) - 'a';
183 if (0 <= index && index < LETTERS) {
186 printf("error: variable must be single letter\n");
192 /* getlin: get line into s, return length */
193 int getlin(char s[], int lim) {
196 while (--lim > 0 && (c=getchar()) != EOF && c != '\n')
198 if (c == '\n' || c == EOF)
204 char buf[MAXOP] = "\n"; /* buffer for current line */
205 int bufp = 0; /* next char to scan in buffer */
207 /* getop: get next operator or numeric operand */
208 int getop(char s[]) {
210 while ((s[0] = c = buf[bufp++]) == ' ' || c == '\t')
215 while ((s[++i] = c = buf[bufp++]) != ' ' && c != '\t' && c != '\n')
222 } else if (s[1] == '\0') {
228 /* negative number or minus */
230 s[++i] = c = buf[bufp++];
231 if (!isdigit(c) && c != '.') {
240 if (!isdigit(c) && c != '.')
241 return c; /* not a number */
242 if (isdigit(c)) /* collect integer part */
243 while (isdigit(s[++i] = c = buf[bufp++]))
245 if (c == '.') /* collect fraction part */
246 while (isdigit(s[++i] = c = buf[bufp++]))