Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* rpn.c - implementation reverse polish notation */
- #include <stdio.h>
- #include <ctype.h>
- #include <stdlib.h>
- #include <stdbool.h>
- #include <errno.h>
- #define STACK_DEPTH 16
- // operations
- #define ADD 0
- #define SUB 1
- #define MUL 2
- #define DIV 3
- // *ups*)
- #define UNDEF_V -1 // undefined value
- #define STACK_OF -2 // stack overflow
- #define STACK_NEO -3 // not enough operands in stack
- void print_help();
- double calculate(char *expr);
- double gettok(char **expr);
- void o_add(double *st, int *top);
- void o_sub(double *st, int *top);
- void o_mul(double *st, int *top);
- void o_div(double *st, int *top);
- void (*operations[])(double *st, int *top) = { o_add, o_sub, o_mul, o_div };
- bool is_end_expr = false;
- bool is_value; // for calculate(). if true,
- // then gettok() return value, otherwise operation
- int main(int argc, char **argv) {
- if (argc >= 3 || argc == 1) {
- print_help();
- return 0;
- }
- double res = calculate(argv[1]);
- if (errno == UNDEF_V) {
- printf("ERROR: Undefined value!\n");
- return UNDEF_V;
- }
- else if (errno == STACK_NEO) {
- printf("ERROR: Not enough operands for operation\n");
- return STACK_NEO;
- }
- else if (errno == STACK_OF) {
- printf("ERROR: Stack overflow(max %d)\n", STACK_DEPTH);
- return STACK_OF;
- }
- printf("Result: ");
- if ((int)res == res)
- printf("%d\n", (int)res);
- else
- printf("%.3f\n", res);
- return 0;
- }
- void print_help() {
- printf("Usage: rpn \"rpn_expression\"\n");
- }
- double calculate(char *expr) {
- double stack[STACK_DEPTH];
- int top = -1;
- double tok;
- do {
- tok = gettok(&expr);
- if (is_value) {
- if (top + 1 >= STACK_DEPTH) {
- errno = STACK_OF;
- return -1;
- }
- stack[++top] = tok;
- }
- else {
- int op = tok;
- switch (op) {
- case ADD:
- case SUB:
- case MUL:
- case DIV:
- if (top + 1 < 2) {
- errno = STACK_NEO;
- return -1;
- }
- operations[op](stack, &top);
- break;
- case UNDEF_V:
- errno = UNDEF_V;
- return -1;
- break;
- }
- }
- } while (!is_end_expr);
- return stack[top];
- }
- double gettok(char **expr) {
- char *next_tok = NULL;
- double res = strtod(*expr, &next_tok);
- /* it's bad idea, because value '0'
- will be considered as UNDEF_V */
- if (res == 0.0) {
- is_value = false;
- switch (**expr) {
- case '+':
- res = ADD;
- break;
- case '-':
- res = SUB;
- break;
- case 'x':
- case '*':
- res = MUL;
- break;
- case '/':
- res = DIV;
- break;
- case '\0':
- is_end_expr = true;
- break;
- default:
- res = UNDEF_V;
- }
- (*expr)++;
- }
- else {
- is_value = true;
- *expr = next_tok;
- }
- // skip spaces
- while (isspace(**expr)) (*expr)++;
- return res;
- }
- void o_add(double *stack, int *top) {
- stack[*top - 1] += stack[*top];
- (*top)--;
- }
- void o_sub(double *stack, int *top) {
- stack[*top - 1] -= stack[*top];
- (*top)--;
- }
- void o_mul(double *stack, int *top) {
- stack[*top - 1] *= stack[*top];
- (*top)--;
- }
- void o_div(double *stack, int *top) {
- stack[*top - 1] /= stack[*top];
- (*top)--;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement