从中缀转换为后缀? Java计算器

时间:2015-05-17 21:05:57

标签: java

我已经完全了解了大量的在线代码,但我已经看过那些,我真的不明白我做错了什么。我创建一个计算器,将表达式从中缀转换为后缀,然后计算它。我正在为它创建课程;主要是一个gui,并被给予。我一直难过这个问题。这两个问题是:

  • 由于某些原因,我的运算符优先级不起作用,当输出到来时,运算符实际上只是向后打印,例如我放入 5 + 5/2,而不是给我5 5 2 / +它给了我5 5 2 + /
  • 我遇到的第二个问题是我的数字不会只打印操作符,就像前面的例子而不是得到5 5 2 / +,我只得到+ /

任何帮助都会受到赞赏,我真的很沮丧,甚至不能再思考了。你知道我的意思。

这是我的评估员代码:

 import java.util.*;
import java.io.*;

public class Evaluator{
  private String infixExp;
  private char opPrec;
  private char op;


public Evaluator(String infixExp){
    this.infixExp = infixExp; // holds my infix expression inputted from gui
    this.opPrec = opPrec; // not being used
    this.op = op;
}
    private boolean isOperator(char op){ // not being used i dont think?
    return(op == '+' || op == '-' || op == '*' || op == '/'
    || op == '^' || op == '(' || op == ')' || op == '%'||  op == '=');
}
 // this is where I order the precedence
private int isLowerPrec(char op) {
    if (op == ('(') || op ==(')') || op ==('='))

    return 0;

    if (op ==('+') || op ==('-'))

    return 1;

    if (op == ('*') || op == ('/'))

    return 2;
    if (op == ('^')|| op ==('%') )

    return 3;
    else
        return -1;
} // end lowerPrecedence
/* converting the infix to postfix, must return expression as a String
   but numbers should be converted to doubles  */

public String Convert(){
    // must use stacks & queues 
    Stack <Character> exp = new Stack<Character>();
    Queue result = new LinkedList(); // not sure how to incorporate queue
    String postfix = "";
    int priority = 0;

    // going through infix expression
    for (int i = 0; i < infixExp.length(); i++){
     // expr(infixExp);
        op = infixExp.charAt(i);

        if(infixExp.length() == 0){
           continue;
        }

       // this is where I call my precedence
       // I know Im close but am missing something
        if(isLowerPrec(op) == -1){
           priority = -1; // pushing numbers onto stack
                if(exp.isEmpty() && priority == -1 ){
                postfix += exp.push(op);

             }
         }
         if(op == '+' || op == '-'){ // come first in stack
            priority = 1;
            isLowerPrec(op);
            if(priority == 1 && isLowerPrec(op) == 1 ){
                postfix += exp.push(op);

               }
           } 

             if(op == '*' || op == '/'){ // come second
                priority = 2;
                //isLowerPrec(op);

                if(priority == 2 && isLowerPrec(op) == 2 || exp.isEmpty()){
                      postfix += exp.push(op);
                     if(exp.peek() == '+' || exp.peek() == '-' ){
                     postfix += exp.push(op);

               }
            }   
        }
        if(op == '^'|| op ==('%')){ // come third
            priority = 3;
            isLowerPrec(op);
            if(priority == 3 && isLowerPrec(op) == 3){
                postfix += exp.push(op);

            }  


        }




       }
         // these must be deleted
        if(op == ')' || op == '(' || op == '='){ // delete
            priority = 4;
            isLowerPrec(op);
             if(priority == 4 && isLowerPrec(op) == 0){
                postfix += exp.push(op);
                 postfix += exp.pop();

            }                 
        }


            return postfix;
   }
 }      

我没有包含gui计算器代码,只是因为它很长。 但是,如果必须的话,我可以感谢您提出的任何帮助或建议!

1 个答案:

答案 0 :(得分:0)

关于你的第二个问题:

您的代码不打印数字的原因是

中的条件exp.isEmpty()
if(exp.isEmpty() && priority == -1 ){
    postfix += exp.push(op);

也就是说,只要将第一个符号推送到exp,就不会再读取数字文字,因为在读取括号时只有pop堆栈。

关于你的第一个问题:

我不确定你的算法应该做什么,但它看起来像它将它可以找到的每个符号添加到字符串postfix,所以基本上它只是复制输入字符串而不是转换它。因此,操作符始终按它们出现在字符串中的顺序打印,而不是按所需顺序打印。

如何解决问题

我无法帮助您直接修复现有代码,因为似乎缺少太多的实现。但是,我可能会帮助您对问题进行不同的研究。

将表达式视为树,数字文字为叶子,运算符为节点。例如,表达式1 + 2 * (3 - 4) / 5将由以下树表示:

enter image description here

现在,要以后缀形式打印此树,您将以后缀形式打印左子树,然后以后缀形式打印右子树,然后打印节点本身的值。我们将按照以下步骤打印树:

  • 打印树叶1(打印"1"
  • 转换/处的子树
    • 转换*处的子树
      • 打印叶子2
      • 转换-处的子树
        • 打印叶子3
        • 打印叶子4
        • 打印运算符-
      • 打印运算符*
    • 打印 leaf 5
    • 打印运算符/
  • 打印运算符+

因此打印的后缀字符串为1 2 3 4 - * 5 / +

幸运的是,这样的表达式树并不难实现:

public abstract class ExpressionTree {
    public abstract String postfixString();
}

public class ExpressionTreeNode extends ExpressionTree {
    final Operator operator;
    final ExpressionTree left, right;

    public ExpressionTreeNode(Operator operator, ExpressionTree left, ExpressionTree right) {
        this.operator = operator;
        this.left = left;
        this.right = right;
    }

    public String toString() {
        return String.format("Node(%s, %s, %s)", operator.toString(), left.toString(), right.toString());
    }

    public String postfixString() {
        return String.format("%s %s %s", left.postfixString(), right.postfixString(), operator.toString());
    }
}

public class ExpressionTreeLeaf extends ExpressionTree {
    final int value;

    public ExpressionTreeLeaf(int value) {
        this.value = value;
    }

    public String toString() {
        return String.format("Leaf(%d)", value);
    }

    public String postfixString() {
        return String.valueOf(value);
    }
}

public enum Operator {
    ADDITION, SUBTRACTION, MULTIPLICATION, DIVISION, POWER, MODULO;

    public String toString() {
        switch (this) {
            case ADDITION:
                return "+";
            case SUBTRACTION:
                return "-";
            case MULTIPLICATION:
                return "*";
            case DIVISION:
                return "/";
            case POWER:
                return "^";
            case MODULO:
                return "%";
            default:
                throw new IllegalStateException("Unknown Operator");
        }
    }
}

如果我们手动构建这个树,我们会得到预期的结果:

System.out.println(
        new ExpressionTreeNode(
                Operator.ADDITION,
                new ExpressionTreeLeaf(1),
                new ExpressionTreeNode(
                        Operator.DIVISION,
                        new ExpressionTreeNode(
                                Operator.MULTIPLICATION,
                                new ExpressionTreeLeaf(2),
                                new ExpressionTreeNode(
                                        Operator.SUBTRACTION,
                                        new ExpressionTreeLeaf(3),
                                        new ExpressionTreeLeaf(4)
                                )
                        ),
                        new ExpressionTreeLeaf(5)
                )
        ).postfixString()
);

现在,在给定字符串的情况下打印后缀表达式的问题被简化为从字符串构建表达式树。您可以通过

构建此树
  1. 发现匹配括号并将括号内的子字符串转换为表达式树。提示:找到第一个结束括号,然后找到以结束括号结尾的子串中的最后一个左括号。另请参阅indexOf()中的substring()String

  2. 如果没有括号,找到具有最高优先级的运算符,并使用这些运算符创建子树,并在其左右两侧创建子表达式。

  3. 继续,直到您处理优先级最低的运算符

  4. 数字文字转换为new ExpressionTreeLeaf(number)