/** * rpn.c - a simple Reverse Polish Notation calculator that reads its * input from standard input. */ #include #include #include #include #include // +-----------+------------------------------------------------------ // | Constants | // +-----------+ // The capacity of the stack #define STACK_CAPACITY 16 // +--------+--------------------------------------------------------- // | Macros | // +--------+ /** * CHECK_ELEMENTS(MIN) * Ensure that there are at least MIN elements on the stack */ #define CHECK_ELEMENTS(MIN) \ if (top < MIN) \ { \ printf ("ERROR: Stack underflow. Skipping operation\n"); \ break; \ } /** * BINARY_STACK_OPERATION(OP) * Code for one of the traditional binary stack operations. */ #define BINARY_STACK_OPERATION(OP) \ CHECK_ELEMENTS(2) --top; \ stack[top-1] = stack[top-1] OP stack[top]; // +------+----------------------------------------------------------- // | Main | // +------+ int main (int argc, char *argv[]) { int stack[STACK_CAPACITY] = { 0 }; // The stack of numbers for RPN evaluation int top = 0; // The top of the stack. That is, the first // empty space on the stack. Also the number // of items on the stack. int ch; // A character we're reading int n; // The next value read. while ((ch = getchar()) != EOF) { switch (ch) { case 'p': // Print if (top == 0) printf ("NO VALUE\n"); else printf ("%d\n", stack[top-1]); break; case '+': BINARY_STACK_OPERATION(+) break; case '-': BINARY_STACK_OPERATION(-) break; case '*': BINARY_STACK_OPERATION(*) break; case '/': BINARY_STACK_OPERATION(/) break; case '%': BINARY_STACK_OPERATION(%) break; case 'n': // Negate CHECK_ELEMENTS(1) stack[top-1] = -stack[top-1]; break; case 's': // Square CHECK_ELEMENTS(1) stack[top-1] = stack[top-1] * stack[top-1]; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': n = ch - '0'; while (isdigit (ch = getchar())) n = 10 * n + ch - '0'; if (top >= STACK_CAPACITY) { printf ("ERROR! Stack overflow\n"); return EXIT_FAILURE; } stack[top] = n; top++; break; default: if ((ch == '\n') || (ch == ' ') || (ch == '\n')) ; // Skip whitespace else printf ("Invalid input: '%c'\n", ch); break; } // switch } // while return EXIT_SUCCESS; } // main