/****************************************************************************** * K&R 5-10 * * Reverse Polish Calculator * (command line args) * * program: rp_calc * usage..: rp_calc expression * EX. rp_calc 1 1 + * date...: 18 November 2024 * * ~yetimach ******************************************************************************/ #include #include #include #define MAXVAL 100 double val[MAXVAL]; int sp = 0, error = 0; void push(double f){ if (sp < MAXVAL) val[sp++] = f; else{ printf("error: stack full, can't push %g", f); error = 1; } } double pop(void){ if (sp > 0) return val[--sp]; else{ printf("error: stack empty (remember: reverse Polish order)\n"); error = 1; return 0.0; } } double n_to_power(double num, int p){ double o_num = num; /*original num*/ if (p == 0) return (num > 0) ? 1 : -1; while (p-- > 1) num *= o_num; return num; } double square(double num){ return num * num; } int main(int argc, char *argv[]){ int type; double op2; while (--argc > 0){ if (isdigit((*++argv)[0]) || isdigit((*argv)[1])){ push(atof(*argv)); } else { type = (*argv)[0]; switch (type) { case '+': push(pop() + pop()); break; case 'x': case '*': /*the * must be escaped in bash shell*/ push(pop() * pop()); break; case '-': op2 = pop(); push(pop() - op2); break; case '/': op2 = pop(); if (op2 != 0) push(pop() / op2); else{ printf("error: zero divisor\n"); error = 1; } break; case '^': case 'p': op2 = pop(); push(n_to_power(pop(), op2)); break; case '%': op2 = pop(); push((int) pop() % (int) op2); break; case 'a': /* push last number, so that */ push(val[sp-1]); /* for ex "12 a +" is like "12 12 +" */ break; case 's': push(square(pop())); break; default: printf("error: unkown command %s\n", *argv); error = 1; break; } } } if (!error) printf("\t%.8g\n", pop()); return 0; }