Оценка Postfix с использованием стеков и C - PullRequest
0 голосов
/ 13 ноября 2011

Я был здесь некоторое время с похожей проблемой, но я думаю, что с неправильным вопросом.Чтобы немного рассказать об этом, я поставил задачу создать C-программу для решения постфиксного выражения в виде

8 7 - 9 * =

. Я думаю, что моя проблема в том, чтомой проф дал неправильный код стека.Я говорю это потому, что постоянно получаю ошибку переполнения стека (lol), а мой стек далеко не заполнен.Если это поможет, я использую Visual Studio 2005. Вот мой код:

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

    #define STACK_SIZE 20

    typedef int Bit;

    Bit contents[STACK_SIZE];
    int top = 0;

    void make_empty(void);
    int is_empty(void);
    int is_full(void);
    void push(Bit i);
    int pop(void);
    void stack_overflow(void);
    void stack_underflow(void);

    int main(void) {
      Bit bit;
      char operation;
      int operand;
      Bit current;
      int result;

        while(scanf("%d",&current)!= '=')
        {
            push(current);
        }

        scanf("%c", &operation);
        while(operation != '=')
        {
            scanf("%d", &operand);
            printf("%d\n",top);
            //Pushes any number into the stack
            if(operand==1||operand==2||operand==3||operand==4||operand==5||operand==6||operand==7||operand==8||operand==9||operand==0)
            {
                printf("entered number loop\n");
                bit = operand;
                if(top==20)
                {
                    stack_overflow();
                }
                push(&bit);
            }

            //Performs subtraction operation
            else if(operation == '-')
            {
                printf("entered minus loop\n");
                if(top==1)
                {
                    stack_underflow();
                }

                result = pop() - pop();

                bit = result;

                if(top==20)
                {
                    stack_overflow();
                }

                push(&bit);
            }

            //Performs addition operation
            else if(operation == '+')
            {
                if(top==1)
                {
                    stack_underflow();
                }

                result = pop() + pop();
                bit = result;

                if(top==20)
                {
                    stack_overflow();
                }

                push(&bit);
            }

            //Performs multiplication operation
            else if(operation == '*')
            {
                if(top==1)
                {
                    stack_underflow();
                }

                result = pop() * pop();
                bit = result;

                if(top==20)
                {
                    stack_overflow();
                }

                push(&bit);
            }

            //Performs division operation
            else if(operation == '/')
            {
                if(top==1)
                {
                    stack_underflow();
                }

                result = pop() / pop();
                bit = result;

                if(top==20)
                {
                    stack_overflow();
                }

                push(&bit);
            }

            else if(operation == '=')
            {
                if(top==0)
                {
                    stack_underflow();
                }

                printf("%d\n",pop());
                break;
            }
        }
  return 0;
}

void make_empty(void) {
  top = 0;
}

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

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

void push(Bit i) {
  if (is_full())
    stack_overflow();
  else
    contents[top++] = i;
}

int pop(void) {
  if (is_empty())
    stack_underflow();
  else
    return contents[top--];
}

void stack_overflow(void) {
  printf("Error: stack overflow!\n");
  exit(EXIT_FAILURE);
}

void stack_underflow(void) {
  printf("Error: stack underflow!\n");
  exit(EXIT_FAILURE);
}

Теперь я понимаю, что мой код сейчас немного варварский, и за это я прошу прощения.Тем не менее, любая помощь или вклад вообще будет принята с благодарностью и спасибо всем заранее.


Хорошо, так что после того, как все учтено, я думаю, что я близок.Все идет в стек правильно и все читается правильно.Тем не менее, моя новая реализация включает в себя создание всего символа и затем преобразование целых чисел, когда они должны быть использованы.Вот мой исходный код еще раз:

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

#define STACK_SIZE 20

typedef int Bit;

char contents[STACK_SIZE];
int top = 0;

void make_empty(void);
int is_empty(void);
int is_full(void);
void push(char i);
char pop(void);
void stack_overflow(void);
void stack_underflow(void);

int main(void) {
    char current = 'a';
    char result = 'a';
    char operation = 'a';
    char char1;
    char char2;
    int number1;
    int number2;

    scanf("%c", &current);
    //While program successfully scanned a number
    while(current != '=')
    {

        //Performs subtraction operation
        if(current == '-')
        {
            printf("entered if 2\n");
            char1 = pop();
            number1 = char1 - '0';
            printf("%d\n", number1);
            char2 = pop();
            number2 = char2 - '0';
            printf("%d\n", number2);
            result = number1 - number2;

            push(result);
        }

        //Performs addition operation
        else if(current == '+')
        {
            printf("entered if 2\n");
            char1 = pop();
            number1 = char1 - '0';
            printf("%d\n", number1);
            char2 = pop();
            number2 = char2 - '0';
            printf("%d\n", number2);
            result = number1 + number2;

            push(result);
        }

        //Performs multiplication operation
        else if(current == '*')
        {
            printf("entered if 2\n");
            char1 = pop();
            number1 = char1 - '0';
            printf("%d\n", number1);
            char2 = pop();
            number2 = char2 - '0';
            printf("%d\n", number2);
            result = number1 * number2;

            push(result);
        }

        //Performs division operation
        else if(current == '/')
        {
            printf("entered if 2\n");
            char1 = pop();
            number1 = char1 - '0';
            printf("%d\n", number1);
            char2 = pop();
            number2 = char2 - '0';
            printf("%d\n", number2);
            result = number1 / number2;

            push(result);
        }

        else
        {
            push(current);
            printf("%c\n", current);
        }

        scanf(" %c", &current);
    }   

    //Prints result
    printf("%c\n",pop());

    return 0;
}

void make_empty(void) {
  top = 0;
}

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

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

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

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

void stack_overflow(void) {
  printf("Error: stack overflow!\n");
  exit(EXIT_FAILURE);
}

void stack_underflow(void) {
  printf("Error: stack underflow!\n");
  exit(EXIT_FAILURE);
}

Пожалуйста, имейте в виду, что я немного поигрался с этим, поэтому есть случайные printfs и бесполезные переменные, все для целей отладки.Всякий раз, когда я запускаю его (с примером ввода 3 5 + =), я получаю:

enter image description here

Итак, еще раз, пожалуйста, извините, мой какой то грязный код, так как я довольно новичок в C, но любойпомощь была бы отличной!

Ответы [ 3 ]

1 голос
/ 13 ноября 2011

Я не вижу проблем со стеком.Но у вас есть как минимум две проблемы:

push(&bit);

push принимает Bit, а не Bit *.Здесь вы должны получить предупреждение, которое вы, вероятно, проигнорировали.Не игнорируйте предупреждения.

while(scanf("%d",&current)!= '=')

Это определенно неправильно.scanf возвращает число успешных вводов.

operand==1||operand==2||operand==3||operand==4||operand==5||operand==6||operand==7||operand==8||operand==9||operand==0

Хотя это не ошибка, почему вы должны писать так?Вы можете легко заменить на:

operand >= 0 && operand <= 9

И может быть еще много проблем.

1 голос
/ 13 ноября 2011

Это бесконечный цикл:

while(scanf("%d",&current)!= '=') { push(current); }

scanf возвращает количество успешно прочитанных полей. В вашем случае это может быть 0 или 1. Вы сравниваете его с «=», что является ASCII 61. Таким образом, «! =» Всегда верно, и вы никогда не пройдете этот цикл.

Кстати, если вы посмотрите, как реализован push, вы увидите, что проверка «переполнения стека» выполняется с помощью функции is_full (). is_full () сравнивает top с STACK_SIZE. Вы сравниваете топ == 20. Вам лучше использовать is_full. Это более абстрактно и будет работать, даже если кто-то изменил STACK_SIZE. Вы могли бы даже опустить ваши проверки для top == 20 и top == 0, потому что единственное, что вы делаете, это вызывает stack_underflow / stack_overflow, что уже выполняется функциями pop / push.

0 голосов
/ 13 ноября 2011

Возникла проблема со следующей строкой:

while(scanf("%d",&current)!= '=')

Функция scanf возвращает количество отсканированных элементов , а не элемент.И при сканировании на %d будет пытаться получить целое число, а не символ.

Я думаю, вы должны искать что-то вроде:

while (scanf("%d",&current) == 1)
    push(current);

, который подтолкнет целые числа кстек до тех пор, пока он больше не сможет сканировать один (т. е. вы получите операцию).

Это почти наверняка ваша проблема, так как этот конкретный scanf обычно будет возвращать только 0 или 1, то есть он никогда не будет равен= (который является шестнадцатеричным 0x3d или десятичным 61, если вы используете ASCII). может возвращать EOF в некоторых случаях, но это все же не даст вам значение 61.

Тот факт, что он никогда return 61 означает, что он просто будет продолжать цикл, помещая значение current в ваш стек до тех пор, пока он не переполнится, что вы и наблюдаете.

...