summaryrefslogtreecommitdiff
path: root/four/calc.c
diff options
context:
space:
mode:
authorMichael Hunteman <michael@huntm.net>2023-07-04 17:03:53 -0500
committerMichael Hunteman <michael@huntm.net>2023-07-06 17:23:45 -0500
commitbfce8f0d0d828209ec0bec71371ee94a7ad62d3e (patch)
treebdf49ca788ca1ca030d5b1cccfd0c9dffeb3f69f /four/calc.c
Initial commit
Diffstat (limited to 'four/calc.c')
-rw-r--r--four/calc.c99
1 files changed, 99 insertions, 0 deletions
diff --git a/four/calc.c b/four/calc.c
new file mode 100644
index 0000000..cb484ad
--- /dev/null
+++ b/four/calc.c
@@ -0,0 +1,99 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#define MAXOP 100
+#define NUMBER '0'
+
+int getop(char[]);
+void push(double);
+double pop(void);
+double peek();
+void ungets();
+
+int
+main()
+{
+ int type, var;
+ double op1, op2, r;
+ char s[MAXOP];
+ char v[26];
+
+ /* reverse Polish calculator */
+ while ((type = getop(s)) != EOF) {
+ switch (type) {
+ case NUMBER:
+ push(atof(s));
+ break;
+ case '+':
+ push(pop() + pop());
+ break;
+ case '*':
+ push(pop() * pop());
+ break;
+ /* to guarantee the right order, the first value must be stored */
+ case '-':
+ op2 = pop();
+ push(pop() - op2);
+ break;
+ case '/':
+ op2 = pop();
+ if (op2 != 0.0) {
+ push(pop() / op2);
+ } else {
+ printf("error: zero divisor\n");
+ }
+ break;
+ case '%':
+ op2 = pop();
+ op1 = pop();
+ if (op1 >= 0.0 && op2 >= 0.0) {
+ push((int)op1 % (int)op2);
+ } else if (op1 < 0.0 || op2 < 0.0) {
+ push(0);
+ } else {
+ printf("error: zero divisor\n");
+ }
+ break;
+ /* print without popping */
+ case 'p':
+ printf("%f\n", peek());
+ break;
+ /* duplicate */
+ case 'd':
+ op2 = peek();
+ push(op2);
+ break;
+ /* swap top two elements */
+ case 's':
+ op2 = pop();
+ op1 = pop();
+ push(op2);
+ push(op1);
+ break;
+ case '=':
+ pop();
+ if (var > 'a' && var < 'z') {
+ v[var - 'a'] = pop();
+ }
+ case '\n':
+ r = pop();
+ printf("\t%.8g\n", r);
+ break;
+ case 'u':
+ ungets();
+ break;
+ default:
+ if (type == 'R') {
+ push(r);
+ } else if (type >= 'a' && type <= 'z') {
+ push(v[type - 'a']);
+ } else {
+ printf("error: unknown command %s\n", s);
+ }
+ break;
+ }
+ var = type;
+ }
+ return 0;
+}