0

我无法在 java 中将堆栈实现为数组。当我尝试使用该数组时,我得到了 nullPointerExceptions。我知道我的其余代码可以工作,因为我能够使用我创建的堆栈的链表实现来运行程序。代码如下:

编辑:堆栈跟踪是

Exception in thread "main" java.lang.NullPointerException
    at LispEvaluator.evaluate(LispEvaluator.java:238)
    at LispEvaluator.fileLoader(LispEvaluator.java:67)
    at Driver.main(Driver.java:16)

这是 lispEvaluator 类的代码

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

        public class LispEvaluator {

        // Current input Lisp expression
        private String inputExpr;
        private Scanner sc;
        private StackList exprStack;
        private StackList tempStack;





        // default constructor
        // set inputExpr to "" 
        // create stack objects
        public LispEvaluator()
        {
        inputExpr = "";
        }



        // default constructor
        // set inputExpr to inputExpression 
        // create stack objects
        public LispEvaluator(String inputExpression) 
        {
            inputExpr = inputExpression;
            }


        // set inputExpr to inputExpression 
        // clear stack objects
        public void reset(String inputExpression) 
        {
        inputExpr = inputExpression;
        StackList exprStack=new StackList(50);
        StackList tempStack=new StackList(50);

        }

        private boolean checkifNumber() {
            return false;
        }
        public void fileLoader(String mode,String file){
            //Validate the user entered mode
            if(mode.equals("0")){
                exprStack=new StackList(50);
                tempStack=new StackList(50);}
            else{
                    ArrayStack exprStack=new ArrayStack(50);
                    ArrayStack tempStack=new ArrayStack(50);

                }
                try{
                //Try to read the array from file
                sc = new Scanner(new File(file));
                while (sc.hasNextLine()) {
                    double result=0;
                    inputExpr=sc.nextLine();
                    reset(inputExpr);

                    result=evaluate();
                    System.out.println(result);
                }
                }


                catch (FileNotFoundException e){
                    System.out.println("Cannot find requested input file");
                    }
                catch(IOException io){
                    System.out.println("General file io error occured. Try again");
                    }




        }




        // 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 = (Double) tempStack.pop();
          double temp=op1;
          while (tempStack.size()>0){
          double op2 = (Double) tempStack.pop();
          temp = temp + op2;}
            return temp;
        }

        private double multiply() {
            double op1 = (Double) tempStack.pop();
          double temp=op1;
          while (tempStack.size()>0){
            double op2 = (Double) tempStack.pop();
            temp = temp * op2;}
              return temp;
        }

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

                    double op1 = (Double) tempStack.pop();
                  double temp=op1;
                  while (tempStack.size()>0){
                    double op2 = (Double) tempStack.pop();
                    temp = temp - op2;}
                      return temp;
        }
        }

        private double divide() {
            double temp;
            if (tempStack.size() == 1) {
                             temp = 1 / (Double) tempStack.pop();
                return temp;
                            }
                 else if (tempStack.size() >=1) {
                    double op1 = (Double) tempStack.pop();
                    temp=op1;

                  while (tempStack.size()>0){
                    double op2 = (Double) tempStack.pop();
                    temp = temp / op2;}
                      return temp;
                }
                return 0;
        }



        private void evaluateCurrentOperation()
        {

        while( exprStack.top().getClass().getName().equals("java.lang.Double") ) {
                tempStack.push( (Double)exprStack.pop() );
            }
            Character operator = (Character)exprStack.pop();
            Double result = null;
            switch( operator ) {
                case '+':
                    result = add();
                    break;
                case '*':
                    result = multiply();
                    break;
                case '-':
                    result = subtract();
                    break;
                case '/':
                    result = divide();
                    break;
            }
            exprStack.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+");
            exprStack.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 == '+') {
                                exprStack.push(nextItem);
                            } else if (nextItem == '-') {
                                exprStack.push(nextItem);
                            } else if (nextItem == '*') {
                                exprStack.push(nextItem);
                              }else if (nextItem == '/'){
                                    exprStack.push(nextItem);
                                }
                             else {
                                exprStack.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 = (Double) exprStack.pop();
        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);
        } }
        */

这是数组堆栈:

public class ArrayStack implements BoundedStack
{
    private int top;
    private Object stk[];
    private int size;
    private int capacity;

    public ArrayStack(){
        top=-1;
        capacity=50;
        stk=new Object[capacity];
    }
    public ArrayStack(int cap)
    {
        top=-1;
        size=0;
        capacity=cap;
        stk=new Object[capacity];
    }

    public void push(Object item) throws FullStackException
    {
        if(isFull()){
            throw new FullStackException("The stack is full. Cannot push more elements onto the stack");}
        else
        {
            stk[++top]=item;
        }
    }

    public Object pop() throws EmptyStackException
    {
        if(isEmpty()==true)
        {
            throw new EmptyStackException("The stack is empty. Cannot pop another element from the stack");
        }
        else{
            Object e=stk[top];
            stk [top]=null;
            --top;
            return e;
        }
    }
    public Object top() throws EmptyStackException{
        if(isEmpty()==true){
            throw new EmptyStackException("The stack is empty. Thus, it has no top");
                }
        return stk[top];
            }
    public int size(){
        return (top+1);
    }

    public boolean isFull(){
        if (size()==capacity){
            return true;}
        return false;
    }
    public boolean isEmpty(){
        if(size()==0){
            return true;}
        return false;
    }
    public int capacity(){
        return capacity;
    }



}
4

2 回答 2

0

最明显的原因是您在使用之前没有初始化数组元素。

如果您正在创建一个数组,例如: -

SomeClass[] arr = new SomeClass[5];

然后在使用你的数组之前,你需要像这样初始化每个数组元素: -

for (int i = 0; i < arr.length; i++) {
    arr[i] = new SomeClass();
}
于 2012-10-28T21:47:36.777 回答
0

如果导致 NullPointerException 的行是该行

exprStack.push(nextItem);

那么问题不在堆栈类中。问题是它exprStack是空的(可能是因为它在这一行之前从未被分配过任何东西)。

您在代码中多次出现与以下错误相同的错误:

public void reset(String inputExpression) {
    inputExpr = inputExpression;
    StackList exprStack=new StackList(50);
    StackList tempStack=new StackList(50);
}

最后两行完全没用:它们将一个新的 StackList 分配给一个局部变量。因此,堆栈被创建,并且立即有资格进行垃圾回收,因为除了超出范围的局部变量之外没有任何东西引用它。

这是发生这种情况的另一个地方:

if (mode.equals("0")){
    exprStack=new StackList(50); 
    tempStack=new StackList(50);
}
else {
    ArrayStack exprStack=new ArrayStack(50);
    ArrayStack tempStack=new ArrayStack(50);
}
于 2012-10-28T22:40:27.347 回答