3

我正在尝试将中缀转换为后缀。例如:“20 + 2 * 3 + (2*8 + 5)* 4”->20 2 3 * + 2 8 * 5 + 4 * + 这是我的代码:

Stack<Character> s = new Stack<Character>();
String postfix = "";
boolean enter = true;
String infixExpr = "20 + 2 * 3     + (2*8 + 5)* 4";

for(int i = 0;i<infixExpr.length();i++){

    if(Character.isDigit(infixExpr.charAt(i)) == true){
        postfix = postfix + infixExpr.charAt(i);
    }
    if(infixExpr.charAt(i) == '+' || infixExpr.charAt(i) == '-'){
        if(s.isEmpty() == true){
            s.push(infixExpr.charAt(i));
        }
        else{
            if(s.peek() == '*' || s.peek() == '/' || s.peek() == '+' || s.peek() == '-'){
                while(s.isEmpty()== false){
                    postfix = postfix + s.pop();
                }
                s.push(infixExpr.charAt(i));
            }
            else{
                s.push(infixExpr.charAt(i));
            }
        }
    }
    if(infixExpr.charAt(i) == '*' || infixExpr.charAt(i) == '/' ){
        if(s.isEmpty() == true){
            s.push(infixExpr.charAt(i));
        }
        else{
            if(s.peek()== '+' || s.peek() == '-' || s.peek() == '('){
                s.push(infixExpr.charAt(i));
            }
            else if(s.peek() == '*' || s.peek() == '/'){
                while(s.isEmpty()== false){
                    postfix = postfix + s.pop();
                }
                s.push(infixExpr.charAt(i));
            }
        }
        if(infixExpr.charAt(i) == '('){
            s.push(infixExpr.charAt(i));
        }
        if(infixExpr.charAt(i) == ')'){
            while(enter){

                if(s.peek() == '('){
                    enter = false;
                }
                else{
                    postfix = postfix + s.pop();
                }
            }
        }
    }
}

因为它写在顶部,我想得到“20 2 3 * + 2 8 * 5 + 4 * +”但我得到“2023 * + 28 * + 54”这是错误的,我多次修改代码但仍然我看不到问题。如果有人可以提供帮助,那就太好了。

4

3 回答 3

2

空间

您没有在后缀变量上放置任何空格。您只检查当前字符是否是“有趣”字符(数字、运算符)之一,而不是是否是空格。结果,如果当前字符是一个空格,你只是跳过它,你不把它复制到后缀。

由于您放在后缀中的唯一内容是您检查过的字符,因此您最终根本没有空格。

你可以像这样解决它:

  • 添加一个名为 的布尔值inNumber,首先将其设置为 true。
  • 每当您处理数字时,在将其添加到 之前postfix,请检查是否inNumber为真。如果是这样,请先添加一个空格。
  • 如果您刚刚处理了一个数字,请设置inNumber为 true。
  • 如果您正在处理运算符,请设置inNumber为 false。
  • 每当您将任何运算符添加到堆栈时,请先添加一个空格。

关于这inNumber一点的想法是,所有属于同一数字的数字之间不应有空格。但是如果postfix在上一轮处理完一个算子之后加上这个数字,那么它就属于一个新的数字,所以那里应该有一个空格。

所以基本上,您的数字处理代码应该如下所示:

        if(Character.isDigit(infixExpr.charAt(i)) == true){
            if ( ! inNumber ) {
                postfix += " ";
            }
            postfix = postfix + infixExpr.charAt(i);
            inNumber = true;
        }

在每一个if表明你应该有一个操作员的地方inNumber = false

在后缀中添加运算符的每个地方都应该如下所示:

        postfix = postfix + " " + s.pop();

处理括号

您的另一个问题是处理().

首先,将检查 and 的代码(放在)for ifand*/。当然,如果该i位置的字符是*or /,它不是 a(或 a)所以这个代码永远不会被调用。

因此,您应该将for 括号移到外面,与on 数字和运算符if处于同一级别。if

另外,您的使用enter是错误的。如果括号里面有括号,比如( 3 + ( 5 + 7 ) ),那么首先)你会一直回到 后面的括号5,这没关系。但随后enter将变为错误,您将无法正确处理外部对。这也是如此,(3 + 5 ) * ( 7 + 2 )因为您不会在程序开始entertrue再次设置。

而不是使用enter,您应该弹出堆栈上的内容并检查它是否是(

        if(infixExpr.charAt(i) == '('){
            inNumber = false;
            s.push(infixExpr.charAt(i));
        }
        if(infixExpr.charAt(i) == ')'){
            inNumber = false;
            char popped;
            while ( ( popped = s.pop() ) != '(' ) {
                    postfix = postfix + " " + popped;
            }
        }        

未弹出的运算符

最后,当您完成扫描输入时完成。但是此时您仍然会有操作员在堆栈上等待!您必须将它们全部弹出并添加到postfix. 所以在循环之后你应该有:

    while ( ! s.isEmpty()) {
        postfix += " " + s.pop();
    }

补充说明:

  • if如果不是使用所有这些语句,而是使用一个语句,那会更好、更清楚switch
  • 将布尔表达式与 进行比较是没有意义的true。正确的写法if (s.isEmpty() == true)是 just if (s.isEmpty()),而不是s.isEmpty() != trueuse ! s.isEmpty()
  • 您没有进行任何语法检查。我不确定这是否是因为这是家庭作业,但在现实生活中,您应该检查 each(是否与 a 匹配,每个运算符都有两个操作数,并且还要处理开头)可能有 a 的负数。-
于 2014-12-16T19:33:02.553 回答
0

问题是您没有添加空格。但是,您不能简单地在每个数字之间添加一个空格。您必须确保没有在整数的数字之间添加空格。为了解决这个问题,我只是在 the 之后添加了一个postfix += " ";if(infixExpr.charAt(i) == '+' || infixExpr.charAt(i) == '-')然后再在if(infixExpr.charAt(i) == '*' || infixExpr.charAt(i) == '/' ). 这背后的逻辑是,一旦遇到运算符,就知道运算符之前的一切都是数字。现在,当我运行程序时,输出为20 2 3 *+2 8 *+5 4. 运算符之间仍然需要添加一些空格,但我会让你处理。

修改后的代码:

    if(infixExpr.charAt(i) == '+' || infixExpr.charAt(i) == '-'){
        postfix += " ";

...

    if(infixExpr.charAt(i) == '*' || infixExpr.charAt(i) == '/' ){
        postfix += " ";
于 2014-12-16T19:57:13.790 回答
-1

这是我的答案代码

#include<stack>
#include<iostream>
using namespace std;
bool high(char a,char b)
{
  if(b==' ')
    return true;
  else if(a==b)
    return false;
  else if(a=='/')
    return true;
  else if(a=='*'&&b!='/')
    return true;
  else if(b=='/')
    return false;
  else if(a!='/'&&b=='*')
    return false;
  else if(b=='-')
    return true;
  else if(a=='-'&&b!='(')
    return false;
  else if(b=='(')
    return true;
  else if(a=='(')
    return true;
  else if(a==')')
    return false;
}
main()
{
int k=0;
string s;
stack<char>s1;
s1.push(' ');
char ch;
while(cin>>ch)
{
    if(ch=='(')
    {
    k=1;
    s1.push(ch);}
    else if(ch>47&&ch<58)
    s.push_back(ch);
    else if(high(ch,s1.top()))
    s1.push(ch);
    else if(!high(ch,s1.top())&&ch!=')')
    {
        while(!s1.empty()&&!high(ch,s1.top()))
        {
            s.push_back(s1.top());
            s1.pop();
        }   
    s1.push(ch);}
    else if(ch==')')
    {
        while(!s1.empty()&&s1.top()!='(')
        {
            s.push_back(s1.top());
            s1.pop();
        }
        s1.pop();
        k=0;
    }

}
while(!s1.empty())
{
    s.push_back(s1.top());s1.pop();
}
cout<<s;
}
于 2017-01-08T16:06:23.137 回答