summaryrefslogtreecommitdiff
path: root/ex5-10.c
diff options
context:
space:
mode:
authorMartin Ashby <martin@ashbysoft.com>2023-02-11 17:35:26 +0000
committerMartin Ashby <martin@ashbysoft.com>2023-02-11 17:35:26 +0000
commitb782b3f9b677d2fcfdbf79a30b3fd4e8a0002aec (patch)
tree537ec6f9ddc220703a215995fda70e5e63592bb9 /ex5-10.c
parentcabe1a14b31edce1a247c367f8e1d7265abec34e (diff)
downloadlearn-c-b782b3f9b677d2fcfdbf79a30b3fd4e8a0002aec.tar.gz
learn-c-b782b3f9b677d2fcfdbf79a30b3fd4e8a0002aec.tar.bz2
learn-c-b782b3f9b677d2fcfdbf79a30b3fd4e8a0002aec.tar.xz
learn-c-b782b3f9b677d2fcfdbf79a30b3fd4e8a0002aec.zip
Exercise 5.10main
Diffstat (limited to 'ex5-10.c')
-rw-r--r--ex5-10.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/ex5-10.c b/ex5-10.c
new file mode 100644
index 0000000..c4afccd
--- /dev/null
+++ b/ex5-10.c
@@ -0,0 +1,113 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#define NUMBER '0'
+#define MAXLINE 1000
+#define MAXVAL 100
+
+int getop(char[]);
+
+void push(double);
+double pop(void);
+void clear(void);
+double peek(void);
+
+// Naïve implementation of remainder operation
+double frem(double f1, double f2) {
+ return f1 - (f2 * (int)(f1 / f2));
+}
+
+/**
+ * Reverse polish notation calculator
+ */
+int main(int argc, char* argv[]) {
+ if (argc <= 1) {
+ fprintf(stderr, "Usage: rpol EXPR...");
+ return 1;
+ }
+ argv++; // Skip program name
+ double op2;
+ for (; *argv != NULL; argv++) {
+ char* tok = *argv;
+ int type = getop(tok);
+ switch (type) {
+ case NUMBER:
+ push(atof(tok));
+ break;
+ case '+':
+ push(pop() + pop());
+ break;
+ case '*':
+ push(pop() * pop());
+ break;
+ case '-':
+ op2 = pop();
+ push(pop() - op2);
+ break;
+ case '/':
+ op2 = pop();
+ if (op2 != 0.0)
+ push(pop() / op2);
+ else
+ printf("error: zero division attempted!\n");
+ break;
+ case '%':
+ op2 = pop();
+ if (op2 != 0.0)
+ push(frem(pop(), op2));
+ else
+ printf("error: zero division attempted!\n");
+ break;
+ case '~':
+ clear();
+ break;
+ default:
+ printf("unknown command %s\n", tok); // Just ignore it?
+ break;
+ }
+ }
+
+ printf("\t%.8g\n", pop());
+ return 0;
+}
+
+int sp; // Stack position
+double val[MAXVAL]; // Value stack
+void push(double f) {
+ if (sp < MAXVAL) {
+ val[sp++] = f;
+ } else {
+ printf("error, stack full\n");
+ }
+}
+
+double pop(void) {
+ if (sp >= 0) {
+ return val[--sp];
+ } else {
+ printf("error, empty stack\n");
+ return 0.0;
+ }
+}
+
+double peek(void) {
+ if (sp >= 0) {
+ return val[sp-1];
+ } else {
+ printf("error, empty stack\n");
+ return 0.0;
+ }
+}
+
+void clear(void) {
+ sp = 0;
+}
+
+int getop(char s[]) {
+ char c = s[0];
+ if (!isdigit(c) && c != '.')
+ return c;
+ return NUMBER;
+}