【问题标题】:Stack/Arithmetic expressions bug堆栈/算术表达式错误
【发布时间】:2021-03-27 11:35:09
【问题描述】:

我在这段代码中有一个错误和错误答案,

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


struct Stack
{
    int top;
    unsigned capacity;
    int* array;
};

struct Stack* createStack(unsigned capacity)
{
    struct Stack* stack = (struct Stack*)
        malloc(sizeof(struct Stack));

    if (!stack)
        return NULL;

    stack->top = -1;
    stack->capacity = capacity;

    stack->array = (int*)malloc(stack->capacity *
        sizeof(int));

    return stack;
}
int isEmpty(struct Stack* stack)
{
    return stack->top == -1;
}
char peek(struct Stack* stack)
{
    return stack->array[stack->top];
}
char pop(struct Stack* stack)
{
    if (!isEmpty(stack))
        return stack->array[stack->top--];
    return '$';
}
void push(struct Stack* stack, char op)
{
    stack->array[++stack->top] = op;
}

int isOperand(char ch)
{
    return (ch >= '0' && ch <= '9');
}

int Prec(char ch)
{
    switch (ch)
    {
    case '+':
    case '-':
        return 1;

    case '*':
    case '/':
        return 2;

    case '^':
        return 3;
    }
    return -1;
}

int infixToPostfix(char* exp)
{
    int i, k;

    struct Stack* stack = createStack(strlen(exp));
    if (!stack)
        return -1;

    for (i = 0, k = -1; exp[i]; ++i)
    {
        if (isOperand(exp[i]))
            exp[++k] = exp[i];
        else if (exp[i] == '(')
            push(stack, exp[i]);
        else if (exp[i] == ')')
        {
            while (!isEmpty(stack) && peek(stack) != '(')
                exp[++k] = pop(stack);
            if (!isEmpty(stack) && peek(stack) != '(')
                return -1;
            else
                pop(stack);
        }
        else
        {
            while (!isEmpty(stack) &&
                Prec(exp[i]) <= Prec(peek(stack)))
                exp[++k] = pop(stack);
            push(stack, exp[i]);
        }

    }

    while (!isEmpty(stack))
        exp[++k] = pop(stack);

    exp[++k] = '\0';
    printf("Reverse Polish Notation:\n");

    char str[1000];

    strcpy(str, exp);

    for (i = 0; str[i]; i++)
    {
        printf("%c ", str[i]);
    }
    printf("\n");
    return 0;
}

int evaluatePostfix(char* exp)
{
    struct Stack* stack = createStack(strlen(exp));
    int i;

    if (!stack) return -1;

    for (i = 0; exp[i]; ++i)
    {
        if (isdigit(exp[i]))
            push(stack, exp[i] - '0');
        else
        {
            int val1 = pop(stack);
            int val2 = pop(stack);
            switch (exp[i])
            {
            case '+': push(stack, val2 + val1); break;
            case '-': push(stack, val2 - val1); break;
            case '*': push(stack, val2 * val1); break;
            case '/': push(stack, val2 / val1); break;
            }
        }
    }
    return pop(stack);
}


int main()
{
    char exp[1000];
    scanf("%s", exp);
    printf("Expression:\n%s\n", exp);

    infixToPostfix(exp);
    printf("Result: \n%d", evaluatePostfix(exp));
    printf("\n");
    return 0;
}

这是程序的想法

目标:实现解析算术表达式的算法。表达式中允许的操作:+、-、*、/、数字文字、括号来设置优先级。

输入格式

输入数据:

作为算法的输入,给出了一行 - 书面算术表达式。

输出格式

结果:

算法的结果是输入表达式的计算值。除了结果外,还需要用后缀表示法(逆波兰表示法)显示原始表达式的记录。

【问题讨论】:

  • 你除以 0。
  • 看起来像被零除。当你评估 .... 5 0 / 你弹出一个零作为 val1 然后 5 作为 val2 接下来你评估 val2 / val1。

标签: c algorithm data-structures stack


【解决方案1】:

崩溃是由以下代码中的除以 0 引起的: case '/': push(stack, val2 / val1); break;

如前所述,循环将 5 和 0 从堆栈中弹出,然后将它们分开。

代码的根本问题是您正在逐个字符地处理操作数,而不是逐个操作数。在您的示例中,infixToPostfix 生成的表达式为“1002100*50/+”。这是行不通的,因为我们无法判断原始数字是 100、2、100,因为它们之间没有空格。您可以通过使 infixToPostfix 在每个数字后添加一个空格来解决此问题。这也需要我们在单独的字符串中构建后缀表达式,因为 k 现在可以超过 i:

int infixToPostfix(char* exp)
{
    int i, k;
    char postfixExp[strlen(exp)];

    struct Stack* stack = createStack(strlen(exp));
    if (!stack)
        return -1;

    for (i = 0, k = -1; exp[i]; ++i)
    {
        if(i != 0 && !isOperand(exp[i]) && isOperand(exp[i-1]))
        {
            //if this digit is not a number but the last digit was, insert a space
            postfixExp[++k] = ' ';
        }
        
        if (isOperand(exp[i]))
            postfixExp[++k] = exp[i];
        else if (exp[i] == '(')
            push(stack, exp[i]);
        else if (exp[i] == ')')
        {
            while (!isEmpty(stack) && peek(stack) != '(')
                postfixExp[++k] = pop(stack);
            if (!isEmpty(stack) && peek(stack) != '(')
                return -1;
            else
                pop(stack);
        }
        else
        {
            while (!isEmpty(stack) &&
                Prec(exp[i]) <= Prec(peek(stack)))
                postfixExp[++k] = pop(stack);
            push(stack, exp[i]);
        }
    }

    while (!isEmpty(stack))
        postfixExp[++k] = pop(stack);

    postfixExp[++k] = '\0';
    strcpy(exp, postfixExp);
    printf("Reverse Polish Notation:\n");


    for (i = 0; exp[i]; i++)
    {
        printf("%c", exp[i]);
    }
    printf("\n");
    return 0;
}

此代码(未经测试,使用风险自负)应输出字符串“100 2 100 *50 /+”。现在需要修改 evaluatePostfix 以读取此字符串并累积数字直到到达空格。它需要读取整个操作数并将该 int 压入堆栈,而不是将单个字符推入/弹出堆栈。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-25
    • 2011-01-25
    • 2021-08-18
    • 2019-03-28
    • 1970-01-01
    • 1970-01-01
    • 2021-05-02
    相关资源
    最近更新 更多