Search code examples
crpn

RPN expression calculating C program bug: unexpected Output for complex expression


Program for calculating a RPN expression, project 6, chapter 10 KN King book:

The program works correctly for simple operations like 8 5 * = (outputs 40), but produces unexpected results for more complex expressions like 8 4 5 - * = it outputs 120, when from the stack operations it should be 8 * (4-5) = -8. first_op is the first and second_op is the second operand.

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

#define STACK_SIZE 99

int top = 0;
char stack[STACK_SIZE];

bool is_full();
bool is_empty();
void push(char);
char pull();
void stack_underflow();
void stack_overflow();

int main(void)
{
    char first_op, sec_op, ch;

    printf("Enter an RPN expression: ");
    for(;;) {
        scanf(" %c", &ch);

        if (ch <= '9' && ch >= '0')
            push(ch);
        else if (ch != '=') {
            sec_op = pull() - 48;
            first_op = pull() - 48;
            switch (ch) {
            case '+': push(first_op + sec_op);
                  break;
            case '-': push(first_op - sec_op);
                  break;
            case '*': push(first_op * sec_op);
                  break;
            case '/': push(first_op / sec_op);
            }
        }

        if (ch == '=') {
            printf("%d\n",  stack[0]);
            exit(EXIT_SUCCESS);
        }
    }
}

bool is_full(void)
{
    return (top == STACK_SIZE);
}

bool is_empty(void)
{
    return top == 0;
}

void push(char ch)
{
    if (is_full())
        stack_overflow();
    else stack[top++] = ch;
}

char pull(void)
{
    if (is_empty())
        stack_underflow();
    else return stack[--top];
}

void stack_overflow(void)
{
    printf("Too complex expression\n");
    exit(EXIT_FAILURE);
}

void stack_underflow(void)
{
    printf("Not enough operands\n");
    exit(EXIT_FAILURE);
}

Solution

  • You have made the ASCII adjustment in the wrong place (when you pull a value from your stack), so when you push a computed value, it will later be unnecessarily adjusted.

    So if instead of

        if (ch <= '9' && ch >= '0')
            push(ch);
        else if (ch != '=') {
            sec_op = pull() - 48;
            first_op = pull() - 48;
    

    you use

        if (ch <= '9' && ch >= '0')
            push(ch - '0');
        else if (ch != '=') {
            sec_op = pull();
            first_op = pull();
    

    you will get the expected result.

    Please note I am using '0' and not the magic number 48.
    You could also use if(isdigit(ch)) which needs ctype.h.