麻烦我的前缀表达式评估器

时间:2011-11-02 18:46:19

标签: java stack expression prefix

我的前缀表达式评估程序出错了。

我尝试运行它时遇到的错误是

Expression (+ (- 6) (* 2 3 4) (/ (+ 3) (- 2 3 1)))
Expression in thread "main" java.lang.NumberFormatException: For input string: "(+ (- 6) (* 2 3 4) (/ (+ 3) (* 1) (- 2 3 1)))"
at sun.misc.FloatingDecimal.readJavaFormatException: For input string "(+ (- 6) (* 2 3 4) (/ (+ 3) (* 1) (- 2 3 1)))"
at sun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)

//code starts here
         import java.util.*;

        public class SimpleLispExpressionEvaluator {

        // Current input Lisp expression
        private String inputExpr;


        // Main stack & temp stack, see algorithm in evaluate()
        private Stack<Object> expressionStack;
        private Stack<Double> tempStack;


        // default constructor
        // set inputExpr to "" 
        // create stack objects
        public SimpleLispExpressionEvaluator()
        {
        inputExpr = "";
        expressionStack = new Stack<Object>();
        tempStack = new Stack<Double>();
        }



        // default constructor
        // set inputExpr to inputExpression 
        // create stack objects
        public SimpleLispExpressionEvaluator(String inputExpression) 
        {
            inputExpr = inputExpression;
            expressionStack = new Stack<Object>();
            tempStack = new Stack<Double>();
            }


        // set inputExpr to inputExpression 
        // clear stack objects
        public void reset(String inputExpression) 
        {
        inputExpr = inputExpression;
        Stack<Object> expressionStack = new Stack<Object>();
        Stack<Double> tempstack =  new Stack<Double>();

        }

        private boolean checkifNumber() {
            return false;
        }


        // This function evaluate current operator with its operands
        // See complete algorithm in evaluate()
        //
        // Main Steps:
        //      Pop operands from expressionStack and push them onto 
        //          tempStack until you find an operator
        //      Apply the operator to the operands on tempStack
        //          Push the result into expressionStack
        //

       `private double add() {
          double op1 = tempStack.pop();
          double op2 = tempStack.pop();
          double temp = op1 + op2;
            return temp;
        }`

        private double multiply() {
            double op1 = tempStack.pop();
            double op2 = tempStack.pop();
            double temp = op1 * op2;
            return temp;
        }

        private double subtract() {
            if (tempStack.size() == 1) {
                            double temp = -tempStack.pop();
                       return temp;
                } else {

            double op1 = tempStack.pop();
            double op2 = tempStack.pop();
            double temp = op1 - op2;
            return temp;
        }
        }

        private double divide() {
            if (tempStack.size() == 1) {
                             double temp = 1 / tempStack.pop();
                return temp;
                            } else if (tempStack.pop() == 0 || tempStack.pop() == null) {
                throw new IndexOutOfBoundsException(); } else {
                    double op1 = tempStack.pop();
                        double op2 = tempStack.pop();
                    double temp = op1 - op2;
                    return temp;
                }
        }








        private void evaluateCurrentOperation()
        {






        while( expressionStack.peek().getClass().getName().equals("java.lang.Double") ) {
                tempStack.push( (Double)expressionStack.pop() );
            }
            Character operator = (Character)expressionStack.pop();
            Double result = null;
            switch( operator ) {
                case '+':
                    result = add();
                    break;
                case '*':
                    result = multiply();
                    break;
                case '-':
                    result = subtract();
                    break;
                case '/':
                    result = divide();
                    break;
            }
            expressionStack.push( result );
                    }






        /**
         * This function evaluates Lisp expression in inputExpr
         * It return result of the expression 
         *
         * The algorithm:  
         *
         * Step 1   Scan the tokens in the expression string.
         * Step 2       If you see an operand, push operand object onto the expressionStack
         * Step 3           If you see "(", next token should be an operator
         * Step 4       If you see an operator, push operator object onto the expressionStack
         * Step 5       If you see ")"  // steps in evaluateCurrentOperation() :
         * Step 6           Pop operands and push them onto tempStack 
         *                  until you find an operator
         * Step 7           Apply the operator to the operands on tempStack
         * Step 8           Push the result into expressionStack
         * Step 9    If you run out of tokens, the value on the top of expressionStack is
         *           is the result of the expression.
         */
        public double evaluate()
        {
        // only outline is given...
        // you need to add statements
        // you may delete or modify  any statements in this method

            // use scanner to tokenize inputExpr
            Scanner inputExprScanner = new Scanner(inputExpr);

            // Use zero or more white space as delimiter,
            // which breaks the string into single character tokens
            inputExprScanner = inputExprScanner.useDelimiter("\\s*");

            // Step 1: Scan the tokens in the string.
            while (inputExprScanner.hasNext())
            {

                // Step 2: If you see an operand, push operand object onto the expressionStack
                if (inputExprScanner.hasNextInt())
                {
                    // This force scanner to grab all of the digits
                    // Otherwise, it will just get one char
                    String dataString = inputExprScanner.findInLine("\\d+");
            expressionStack.push(new Double(dataString));

            // more ...
                }
                else
                {
            // Get next token, only one char in string token
                    String aToken = inputExprScanner.next();
                    char item = aToken.charAt(0);
                    String nextToken;
            char nextItem;
                    switch (item)
                    {
                    // Step 3: If you see "(", next token should be an operator
                case '(':
                    nextToken = inputExprScanner.next();
                    nextItem = nextToken.charAt(0);
                    // Step 4: If you see an operator, push operator object onto the expressionStack
                if (nextItem == '+') {
                                expressionStack.push(nextItem);
                            } else if (nextItem == '-') {
                                expressionStack.push(nextItem);
                            } else if (nextItem == '*') {
                                expressionStack.push(nextItem);
                            } else {
                                expressionStack.push(nextItem);
                            }



                break;
                    // Step 5: If you see ")"  // steps 6,7,8 in evaluateCurrentOperation() 
                case ')':

                    try {
                    evaluateCurrentOperation();
                } catch (EmptyStackException e) {
                    break;
                }

                break;
                        default:  // error
                            throw new RuntimeException(item + " is not a legal expression operator");
                    } // end switch
                } // end else
            } // end while

            // Step 9: If you run out of tokens, the value on the top of expressionStack is
            //         is the result of the expression.
            //
            //         return result
            double result = new Double(inputExpr);
        return  result;   
        }


        // This static method is used by main() only
        private static void evaluateExprt(String s, SimpleLispExpressionEvaluator expr) 
        {
            Double result;
            System.out.println("Expression " + s);
        expr.reset(s);
            result = expr.evaluate();
            System.out.printf("Result %.2f\n", result);
            System.out.println("-----------------------------");
        }

        // simple tests 
        public static void main (String args[])
        {
            SimpleLispExpressionEvaluator expr= new SimpleLispExpressionEvaluator();
            String test1 = "(+ (- 6) (* 2 3 4) (/ (+ 3) (* 1) (- 2 3 1)))";
            String test2 = "(+ (- 632) (* 21 3 4) (/ (+ 32) (* 1) (- 21 3 1)))";
            String test3 = "(+ (/ 2) (* 2) (/ (+ 1) (+ 1) (- 2 1 )))";
            String test4 = "(+ (/2))";
            String test5 = "(+ (/2 3 0))";
            String test6 = "(+ (/ 2) (* 2) (/ (+ 1) (+ 3) (- 2 1 ))))";
        evaluateExprt(test1, expr);
        evaluateExprt(test2, expr);
        evaluateExprt(test3, expr);
        evaluateExprt(test4, expr);
        evaluateExprt(test5, expr);
        evaluateExprt(test6, expr);
        } }

1 个答案:

答案 0 :(得分:1)

evaluate的第9步没有做评论:

        // Step 9: If you run out of tokens, the value on the top of expressionStack is
        //         is the result of the expression.
        //
        //         return result
        double result = new Double(inputExpr);

它试图将整个输入字符串转换为double,而不是检索表达式堆栈的顶部。它应该像

        double result = (Double)expressionStack.pop();

还要注意,已实施的运营商不接受3个或更多参数 - (* 2 3 4)不起作用。