中缀表达式求解器的空堆栈异常

时间:2017-11-07 06:22:32

标签: java exception stack infix-notation

因此,该程序假设从GUI中获取包含整数操作数和四个算术运算符(+ - * /)的语法正确的中缀表达式并显示结果。我在括号中输入表达式时遇到麻烦。

例如,这个表达式

5+3-2 

将返回6,但括号中的表达式相同

(5+3-2)

返回一个空堆栈异常。

我尽可能小心地试图通过这个,但我知道有用。编译器将错误指向第三个while循环,这表明我最好的猜测是堆栈valueStack当时没有两个值,但我似乎无法弄清楚原因。谁能帮我弄清楚我做错了什么?

   public String infix(String expression)
   {
      expression=expression.replaceAll("[\t\n ]", "");
      String operator = "*/+-";
      int value1, value2;
      char ch;
      StringTokenizer tokenizer = new StringTokenizer(expression, operator, true); 
      Stack<Integer> valueStack = new Stack<Integer>();
      Stack<Character> operatorStack = new Stack<Character>();

      while(tokenizer.hasMoreTokens())
      {
         String token = tokenizer.nextToken();
         if(isInteger(token) == true)
            valueStack.push(Integer.parseInt(token));
         else if(token.charAt(0) == '(')
            operatorStack.push(token.charAt(0));
         else if(token.charAt(0) == ')')
            while(operatorStack.peek() != '(')
            {
               value1 = valueStack.pop();
               value2 = valueStack.pop();
               valueStack.push(solver(value1, value2, operatorStack.pop()));
               operatorStack.pop();
            }
         else if(token.charAt(0) == '+' || token.charAt(0) == '-' || token.charAt(0) == '*' || token.charAt(0) == '/')
         {
            while(!operatorStack.isEmpty() && precedence(token.charAt(0)) <= precedence(operatorStack.peek()))
            {
               value1 = valueStack.pop(); 
               value2 = valueStack.pop(); //empty stack error starts here
               valueStack.push(solver(value1, value2, operatorStack.pop()));
            }
            operatorStack.push(token.charAt(0));
         }
      }
      while(!operatorStack.isEmpty())
      {
         value1 = valueStack.pop();
         value2 = valueStack.pop();
         ch = operatorStack.pop();
         valueStack.push(solver(value1, value2, ch));
      }


      String result = Integer.toString(valueStack.pop());
      return result;     
   }  //End of infix

   public static boolean isInteger(String s)
   {
      try
      { 
         Integer.parseInt(s);
      } 
      catch(NumberFormatException e)
      {
         return false; 
      } 
      catch(NullPointerException e) 
      {
         return false;
      }
      return true;
   } // end of isInteger

   public int solver( int value1, int value2, char operator)
   {
      try
      {
         if(operator == '*')
            return value2 * value1;
         else if(operator == '/')
            return value2 / value1;
         else if(operator == '+')
            return value2 + value1;
         else if(operator == '-')
            return value2 - value1;
         else
            return 0;
      }
      catch(ArithmeticException e )
      {
         JOptionPane.showMessageDialog(null, "Division by Zero");
      }
      return 0;
   } // end of solver

   public int precedence(char op)
   {
      if(op == '+' || op == '-')
         return 1;
      else if(op == '*' || op == '/')
         return 2;
      else
         return 0;
   }   // end of precedence

1 个答案:

答案 0 :(得分:0)

首先,我只修复了带括号的表达式周围的崩溃错误。我没有测试其他的东西,对不起。

有一些问题(我在调试代码中包含了注释)但实质上你假设你在一个堆栈上有2个值,而实际上你只有一个。这是因为你穿的第一个号码从来没有被戴上,因为它有一个“(”附加它。第一个标记是“(5”而不是“(”,所以它永远不会到达5,无论如何这是代码哈哈

import java.util.*;

import javax.swing.JOptionPane;

public class Calc {

    public String infix(String expression)
    {
        expression=expression.replaceAll("[\t\n ]", "");
        String operator = "(*/+-)"; // I added (,) see line 20 for why ...
        int value1, value2;
        char ch;
        StringTokenizer tokenizer = new StringTokenizer(expression, operator, true); 
        Stack<Integer> valueStack = new Stack<Integer>();
        Stack<Character> operatorStack = new Stack<Character>();

        while(tokenizer.hasMoreTokens())
        {
            String token = tokenizer.nextToken();
            // the token here was "(5" when really it should be 5, therefore 5 doesn't get put on the value stack, which has consequences
            // see line 37 ...
            if(isInteger(token) == true)
                valueStack.push(Integer.parseInt(token));
            else if(token.charAt(0) == '(')
                operatorStack.push(token.charAt(0));
            else if(token.charAt(0) == ')')
                while(operatorStack.peek() != '(') // also need to check if the stack is empty here ...
                {
                    value1 = valueStack.pop();
                    value2 = valueStack.pop();
                    valueStack.push(solver(value1, value2, operatorStack.pop()));
                    operatorStack.pop();
                    // also need to check if the stack is empty here ...
                    if (operatorStack.isEmpty())
                        break;
                }
            else if(token.charAt(0) == '+' || token.charAt(0) == '-' || token.charAt(0) == '*' || token.charAt(0) == '/')
            {
                while(!operatorStack.isEmpty() && precedence(token.charAt(0)) <= precedence(operatorStack.peek()))
                {   // the bug happens because there is only one value [3] on the valueStack, and here you assume there are 2 (should be 3,5)
                    value1 = valueStack.pop(); 
                    value2 = valueStack.pop(); //empty stack error starts here
                    valueStack.push(solver(value1, value2, operatorStack.pop()));
                }
                operatorStack.push(token.charAt(0));
            }
        }
        while(!operatorStack.isEmpty())
        {
            value1 = valueStack.pop();
            value2 = valueStack.pop();
            ch = operatorStack.pop();
            valueStack.push(solver(value1, value2, ch));
        }


        String result = Integer.toString(valueStack.pop());
        return result;     
    }  //End of infix

    public static boolean isInteger(String s)
    {
        try
        { 
            Integer.parseInt(s);
        } 
        catch(NumberFormatException e)
        {
            return false; 
        } 
        catch(NullPointerException e) 
        {
            return false;
        }
        return true;
    } // end of isInteger

    public int solver( int value1, int value2, char operator)
    {
        try
        {
            if(operator == '*')
                return value2 * value1;
            else if(operator == '/')
                return value2 / value1;
            else if(operator == '+')
                return value2 + value1;
            else if(operator == '-')
                return value2 - value1;
            else
                return 0;
        }
        catch(ArithmeticException e )
        {
            JOptionPane.showMessageDialog(null, "Division by Zero");
        }
        return 0;
    } // end of solver

    public int precedence(char op)
    {
        if(op == '+' || op == '-')
            return 1;
        else if(op == '*' || op == '/')
            return 2;
        else
            return 0;
    }   // end of precedence


    public static void main (String [] args) {
        Calc c = new Calc();

        System.out.println(c.infix("(5+2-1)")); // heyy it works now :)
    }

}

只需快速编辑,上面的代码仍然会为这样的表达式(5+(3 + 2))抛出异常,即嵌套括号,所以我也为此添加了一个快速(也许不是很漂亮)修复:< / p>

import java.util.*;

import javax.swing.JOptionPane;

public class Calc {

    public String infix(String expression)
    {
        expression=expression.replaceAll("[\t\n ]", "");
        String operator = "(*/+-)"; // I added (,) see line 20 for why ...
        int value1, value2;
        char ch;
        StringTokenizer tokenizer = new StringTokenizer(expression, operator, true); 
        Stack<Integer> valueStack = new Stack<Integer>();
        Stack<Character> operatorStack = new Stack<Character>();

        // added this in:
        boolean stopParsingBrackets = false;

        while(tokenizer.hasMoreTokens())
        {
            String token = tokenizer.nextToken();
            // the token here was "(5" when really it should be 5, therefore 5 doesn't get put on the value stack, which has consequences
            // see line 37 ...
            if(isInteger(token) == true)
                valueStack.push(Integer.parseInt(token));
            else if(token.charAt(0) == '(' && stopParsingBrackets)
                operatorStack.push(token.charAt(0));
            else if(token.charAt(0) == ')' && stopParsingBrackets)
                while(operatorStack.peek() != '(') // also need to check if the stack is empty here ...
                {
                    value1 = valueStack.pop();
                    value2 = valueStack.pop();
                    valueStack.push(solver(value1, value2, operatorStack.pop()));
                    operatorStack.pop();
                    // also need to check if the stack is empty here ...
                    if (operatorStack.isEmpty()) {
                        stopParsingBrackets = true;
                    }
                }
            else if(token.charAt(0) == '+' || token.charAt(0) == '-' || token.charAt(0) == '*' || token.charAt(0) == '/')
            {
                while(!operatorStack.isEmpty() && precedence(token.charAt(0)) <= precedence(operatorStack.peek()))
                {   // the bug happens because there is only one value [3] on the valueStack, and here you assume there are 2 (should be 3,5)
                    value1 = valueStack.pop(); 
                    value2 = valueStack.pop(); //empty stack error starts here
                    valueStack.push(solver(value1, value2, operatorStack.pop()));
                }
                operatorStack.push(token.charAt(0));
            }
        }
        while(!operatorStack.isEmpty())
        {
            value1 = valueStack.pop();
            value2 = valueStack.pop();
            ch = operatorStack.pop();
            valueStack.push(solver(value1, value2, ch));
        }


        String result = Integer.toString(valueStack.pop());
        return result;     
    }  //End of infix

    public static boolean isInteger(String s)
    {
        try
        { 
            Integer.parseInt(s);
        } 
        catch(NumberFormatException e)
        {
            return false; 
        } 
        catch(NullPointerException e) 
        {
            return false;
        }
        return true;
    } // end of isInteger

    public int solver( int value1, int value2, char operator)
    {
        try
        {
            if(operator == '*')
                return value2 * value1;
            else if(operator == '/')
                return value2 / value1;
            else if(operator == '+')
                return value2 + value1;
            else if(operator == '-')
                return value2 - value1;
            else
                return 0;
        }
        catch(ArithmeticException e )
        {
            JOptionPane.showMessageDialog(null, "Division by Zero");
        }
        return 0;
    } // end of solver

    public int precedence(char op)
    {
        if(op == '+' || op == '-')
            return 1;
        else if(op == '*' || op == '/')
            return 2;
        else
            return 0;
    }   // end of precedence


    public static void main (String [] args) {
        Calc c = new Calc();

        System.out.println(c.infix("(5+(2-1+2))")); // heyy it works now :)
    }

}