diff options
author | Daniel <steew0x8@protonmail.com> | 2021-11-03 23:31:16 +0100 |
---|---|---|
committer | Daniel <steew0x8@protonmail.com> | 2021-11-03 23:31:16 +0100 |
commit | d465d6e672eba42da6e2dd729e02e6b78b0bf22a (patch) | |
tree | a2b80da6c75300670f46967a3b1a90db0e8e18b9 | |
parent | 27462e85046b14a0bb5209159a49447d17cbe4a8 (diff) | |
download | rpncalc-d465d6e672eba42da6e2dd729e02e6b78b0bf22a.tar.gz |
initial commit
-rw-r--r-- | main.c | 65 | ||||
-rw-r--r-- | meson.build | 3 | ||||
-rw-r--r-- | state.c | 6 | ||||
-rw-r--r-- | util.c | 32 |
4 files changed, 106 insertions, 0 deletions
diff --git a/main.c b/main.c new file mode 100644 index 0000000..f72d7aa --- /dev/null +++ b/main.c @@ -0,0 +1,65 @@ +#include <stdio.h> +#include "state.h" +#include "util.h" +#include <stdlib.h> +#include <err.h> + +#define BUF_SIZE 50 + +/* rpncalc: a simple reverse polish notation calculator */ +int main() { + + /* initialize state struct and its values */ + state s; + /* default input buffer is stdin */ + s.defbuf = stdin; + /* default output buffer is stdout */ + s.defout = stdout; + s.last_op = 0; + /* set default interactive prompt */ + s.prompt = "[%d]> "; + stack stack = {{0}, 0}; + /* initialize value stack */ + s.stack = stack; + s.command_count = 0; + + /* start reading from defbuf */ + char buf[BUF_SIZE]; + while(1){ + fprintf(s.defout, s.prompt, s.command_count, s.last_op); + s.last_op = 0; + if (s.stack.count == STACK_SIZE) err(1, "exceeded stack size"); + fgets(buf, BUF_SIZE, s.defbuf); + TYPE t = discriminate(buf); + if (t == OPERATOR ) { + if (s.stack.count == 1) { + fprintf(s.defout, "not enough arguments\n"); + continue; + } + char operator = buf[0]; + if (operator == '+') { + s.stack.val[s.stack.count-2] = s.stack.val[s.stack.count-1]+s.stack.val[s.stack.count-2]; + s.stack.val[s.stack.count--] = 0; /* lower count by 1 */ + s.last_op = '+'; + } else if (operator == '-') { + s.stack.val[s.stack.count-2] = s.stack.val[s.stack.count-2]-s.stack.val[s.stack.count-1]; + s.stack.val[s.stack.count--] = 0; /* lower count by 1 */ + s.last_op = '-'; + } else if (operator == '*') { + s.stack.val[s.stack.count-2] = s.stack.val[s.stack.count-2]*s.stack.val[s.stack.count-1]; + s.stack.val[s.stack.count--] = 0; /* lower count by 1 */ + s.last_op = '*'; + } else if (operator == '/') { + s.stack.val[s.stack.count-2] = s.stack.val[s.stack.count-2]/s.stack.val[s.stack.count-1]; + s.stack.val[s.stack.count--] = 0; /* lower count by 1 */ + s.last_op = '/'; + } + } else { + s.stack.val[s.stack.count++]=strtod(buf, NULL); + } + s.command_count++; + for (int i = 0; i < s.stack.count; i++) { + fprintf(s.defout,"%d → %f\n",i, s.stack.val[i]); + } + } +} diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..e6012bf --- /dev/null +++ b/meson.build @@ -0,0 +1,3 @@ +project('rpncalc', 'c') +src = ['main.c', 'state.c', 'util.c'] +executable('rpncalc', src) diff --git a/state.c b/state.c new file mode 100644 index 0000000..2c504e8 --- /dev/null +++ b/state.c @@ -0,0 +1,6 @@ +#include "state.h" + +void push(state *s, double d) { + s->stack.val[s->stack.count+1] = d; + s->stack.count += 1; +} diff --git a/util.c b/util.c new file mode 100644 index 0000000..555c445 --- /dev/null +++ b/util.c @@ -0,0 +1,32 @@ +#include "util.h" +#include <math.h> + +char OPERATOR_LIST[] = { + '+', + '-', + '*', + '/', + 0 +}; + +int is_decimal(char *s) { + for (int i = 0; s[i] != 0; i++) { + if (s[i] == ',' || s[i] == '.') return 1; + } + return 0; +} + +int is_operator(char *s) { + for (int i = 0; OPERATOR_LIST[i] != 0; i++) { + if (s[0] == OPERATOR_LIST[i]) return 1; + } + return 0; +} + +TYPE discriminate(char *s) { + if (is_decimal(s)) { + return DOUBLE; + } else if (is_operator(s)) { + return OPERATOR; + } else return INT; +} |