【问题标题】:Evaluate Infix expression without converting it into postfix [duplicate]评估中缀表达式而不将其转换为后缀[重复]
【发布时间】:2019-12-27 07:14:24
【问题描述】:

我试图在 1 遍中评估一个中缀表达式而不将其转换为后缀,但它没有为某些表达式提供正确的输出。例如: 3-5*10/5+10 , (45+5)-5*(100/10)+5

有人可以在 cpp.

上一个问题的链接:How to evaluate an infix expression in just one scan using stacks?

请不要将其标记为重复,因为我已尝试在上述给定线程中回答的算法但无济于事。

#include<bits/stdc++.h>

int isoperand(char x)
{
    if(x == '+' || x=='-'|| x=='*' || x=='/' || x==')' || x=='(')
        return 0;
    return 1;
}

int Pre(char x)
{
    if(x == '+' || x == '-')
        return 1;
    if(x == '*' || x == '/')
        return 3;
    return 0;
}

int infixevaluation(std::string exp)
{
    std::stack<int> s1; //Operand Stack
    std::stack<char> s2; //Operator Stack
    int i,x,y,z,key;
    i=0;
    while(exp[i]!='\0')
    {

        if(isoperand(exp[i]))
        {
            key = exp[i]-'0';
            s1.push(key);
            i++;
        }
        else if(!isoperand(exp[i]) && s2.empty())
            s2.push(exp[i++]);
        else if(!isoperand(exp[i]) && !s2.empty())
        {
            if(Pre(exp[i])>Pre(s2.top()) && exp[i]!=')')
                s2.push(exp[i++]);
            else if(exp[i]==')' && s2.top() == '(')
            {
                s2.pop();
                i++;
            }
            else if(exp[i]=='(')
                s2.push(exp[i++]);
            else
            {
                x = s1.top();
                s1.pop();
                y = s2.top();
                s2.pop();
                z = s1.top();
                s1.pop();
                if(y == '+')
                    s1.push(z+x);
                else if(y == '-')
                    s1.push(z-x);
                else if(y == '*')
                    s1.push(x*z);
                else if(y == '/')
                    s1.push(z/x);
            } 
        }
    }
    while(!s2.empty())
    {
        x = s1.top();
        s1.pop();
        y = s2.top();
        s2.pop();
        z = s1.top();
        s1.pop();
        if(y == '+')
            s1.push(x+z);
        else if(y == '-')
            s1.push(z-x);
        else if(y == '*')
            s1.push(x*z);
        else if(y == '/')
            s1.push(z/x);
    }
    return s1.top();
}

int main(int argc, char const *argv[])
{
    std::string s;
    getline(std::cin,s);
    std::cout<<infixevaluation(s)<<std::endl;
    return 0;
}

【问题讨论】:

  • 预期输出是多少,实际输出是多少?另外,debugging your program 是否允许您缩小问题所在?
  • 它为表达式 (45+5)-5*(100/10)+5 和 3-5*10/5+10 输出为 1 而不是3.
  • 异常是崩溃,不是输出。您的下一步应该是debug your program 以确定崩溃发生的位置。然后简化您的程序(删除功能),直到您有一个 minimal reproducible example 来演示崩溃。
  • 小心#include&lt;bits/stdc++.h&gt; 它包含了几乎整个标准库,把你的代码变成了雷区。你还没有加入using namespace std;,这确实让 stdc++.h 成为一个坏主意,因为你的代码变成了一个非常大的雷区,但是有一个 whole bunch of other reasons not to use it.
  • 如果你使用有意义的变量名,你的代码会更容易理解。例如,s1 可以是 operandStack。而不是x = s1.top()operand1 = operandStack.top() 怎么样?在生产环境中,我什至不会检查此代码是否正确运行,直到它具有有意义的变量名称。

标签: c++ stack infix-notation


【解决方案1】:

您的代码只能处理一位数的操作数——而且它没有检查格式错误的输入,所以当您有一个多位数的操作数时,它就会跑偏。

对于前者,最简单的解决方法是在看到数字时扫描数字 -- 将 if (isoperand(exp[i]) 子句更改为:

    if (isdigit(exp[i])) {
        int value = 0;
        while (isdigit(exp[i]))
            value = value * 10 + exp[i++] - '0';
        s1.push(value);
    } else ...

对于错误检查,您应该执行以下操作

  • 检查空格和其他无效字符并拒绝或跳过它们
  • 跟踪匹配的最后一个标记是操作数还是运算符,并为两个连续的操作数或两个连续的运算符而不是() 给出错误

【讨论】:

  • 谢谢!有效。我用笔和纸来追踪代码,我一次推了 2 位数字。应该使用调试器。傻我!完整解决方案链接:ideone.com/IV8PAU
猜你喜欢
  • 2014-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-13
  • 2016-08-16
  • 1970-01-01
相关资源
最近更新 更多