简体   繁体   English

如何避免ArrayIndexOutOfbounds异常?

[英]how to avoid ArrayIndexOutOfbounds Exception?

I am trying to solve a infix expression using stacks and my program seems to throw an ArrayIndexOutOfBoundsException . 我试图使用堆栈解决中缀表达式,我的程序似乎抛出一个ArrayIndexOutOfBoundsException

Can you guide me on how to solve my bug in the code? 你能指导我如何在代码中解决我的错误吗?

Program class 课程班

public class CS6084BTolani {

    public static String evaluateInfix(String exps)
    {
        exps = exps.replaceAll(" ", "");//removing white spaces
        System.out.println(exps);

        StackADT<Double> values = new StackADT<Double>(exps.length());//Stack for Operands
        StackADT<String> ops = new StackADT<String>(exps.length());//for operators


        StringTokenizer tokens = new StringTokenizer(exps, "()^*/+-", true);//to seperate all the operands and operators 

        while(tokens.hasMoreTokens())
        {
            String tkn = tokens.nextToken();

            if(tkn.equals("(")) 
            {
                ops.push(tkn);
                System.out.println("ADDING to ops : "+ops.peek());
            } 
            else if(tkn.matches("\\d+\\.\\d+")||tkn.matches("\\d+"))
            {

                values.push(Double.valueOf(tkn));
                System.out.println("ADDING to values : "+values.peek());
            }
            else if (tkn.equals("^") || tkn.equals("*") || tkn.equals("/") || tkn.equals("+") || tkn.equals("-"))
            {
                while (!ops.isEmpty() && hasPrecedence(tkn, ops.peek()))
                  values.push(applyOp(ops.pop(), values.pop(), values.pop()));
              System.out.println("ADDING to values: "+values.peek());

                // Push current token to 'ops'.
                ops.push(tkn);
                System.out.println("ADDING to ops: "+ops.peek());
            }
            else if(tkn.equals(")"))
            {
                while (!(ops.peek()).equals("("))
                {
                  values.push(applyOp(ops.pop(), values.pop(), values.pop()));
                  System.out.println("ADDING to values: "+values.peek());
                }
                ops.pop();
            }


        }

        while (!ops.isEmpty())
            values.push(applyOp(ops.pop(), values.pop(), values.pop()));

        // Top of 'values' contains result, return it
        return String.valueOf(values.pop());
    }

    public static boolean hasPrecedence(String op1, String op2)
    {
        if (op2 == "(" || op2 == "(")
            return false;
        if ( (op1 == "^" ) && (op2 == "+" || op2 == "-"))
            return false;
        if ( (op1 == "^" ) && (op2 == "*" || op2 == "/"))
            return false;
        if ( (op1 == "*" || op1 == "/") && (op2 == "+" || op2 == "-"))
            return false;
        else
            return true;
    }

    public static double applyOp(String op, double b, double a)
    {
        switch (op)
        {
        case "^":
            return Math.pow(a,b);
        case "+":
            return a + b;
        case "-":
            return a - b;
        case "*":
            return a * b;
        case "/":
            if (b == 0)
                throw new
                UnsupportedOperationException("Cannot divide by zero");
            return a / b;
        }
        return 0;
    }

    public static void main(String a[]) throws Exception
    {
        //Input ip = new Input("inputData4B.txt");
        String expOne = "(100.0 + 2.3)";//ip.getFirstString();
        System.out.println("Answer: "+evaluateInfix(expOne));
        //String expTwo = ip.getSecondString();
        //System.out.println("Answer: "+evaluateInfix(expTwo));
        //String expThree = ip.getThirdString();
        //System.out.println("Answer: "+evaluateInfix(expThree));
        //String expFour = ip.getFourthString();
        //System.out.println("Answer: "+evaluateInfix(expFour));
    }
}

Stack class 堆栈类

class StackADT<T extends Object> {

    private int stackSize;
    private T[] stackArr;
    private int top;


    public StackADT(int size) 
    {
        stackSize = size;
        stackArr = (T[]) new Object[stackSize];
        top = -1;
    }
    public void push(T element){

        stackArr[++top] = element;
    }
    public T pop()  
    {
        if(isEmpty())
        {
            System.out.println("Stack is isEmpty.");
        }
        T element = stackArr[top--];
        return element;
    }
    public T peek() 
    {
        return stackArr[top];
    }

    public boolean isEmpty() 
    {
        return (top == -1);
    }    
}

On running it is like this: 在运行它是这样的:

java CS6084BTolani

(100.0+2.3)


ADDING to ops : (

ADDING to values : 100.0

Stack is isEmpty.

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1

at StackADT.pop(CS6084BTolani.java:139)

at CS6084BTolani.evaluateInfix(CS6084BTolani.java:38)

at CS6084BTolani.main(CS6084BTolani.java:102)

This is not an answer but a suggestion to make the program easier to debug - it won't fit in a comment :) 这不是一个答案,而是一个让程序更容易调试的建议 - 它不适合评论:)

else if (tkn.equals("^") || tkn.equals("*") || tkn.equals("/") || tkn.equals("+") || tkn.equals("-"))
    {
        while (!ops.isEmpty() && hasPrecedence(tkn, ops.peek())) {
          values.push(applyOp(ops.pop(), values.pop(), values.pop()));
          System.out.println("ADDING calculations to values: "+values.peek());
        }

Analysis 分析

It seems to be a logical error (conceptual mistake?). 这似乎是一个逻辑错误(概念错误?)。

There is the attempt to evaluate an expression sequentially using tokens. 尝试使用令牌顺序评估表达式。 When the next operation token is available, the operation is being applied, but there is no check that the value stack size is greater or equal to the number of values required to perform (interpret) the operation before popping the values. 当下一个operation token可用时,正在应用operation ,但是没有检查value stack大小是否大于或等于在弹出值之前执行(解释)操作所需的值的数量。 This is why the last printed message is Stack is isEmpty. 这就是为什么最后打印的消息是Stack is isEmpty. .

General note 一般说明

The algorithm — the infix expressions evaluation algorithm. 算法 - 中缀表达式评估算法。

If the goal is to learn how to design the algorithm, then try to design it by yourself. 如果目标是学习如何设计算法,那么尝试自己设计。 Otherwise, learn the algorithm using its description, for example, from this source . 否则,请使用其描述(例如,从此来源)学习算法。

Before updating the current implementation, please try to understand what is wrong with it: compare it with the designed or described version. 在更新当前实现之前,请尝试了解它的错误:将其与设计或描述的版本进行比较。 Right after that, update the implementation or create a new one if a lot of changes are required. 在此之后,如果需要进行大量更改,请更新实施或创建新实施。

Solution

Currently, I see a problem with operation precedence handling. 目前,我发现操作优先级处理存在问题。 Please consider the following operation handling: 请考虑以下操作处理:

else if (tkn.equals("^") || tkn.equals("*") || tkn.equals("/") || tkn.equals("+") || tkn.equals("-")) {
    if (!ops.isEmpty() && !hasPrecedence(tkn, ops.peek())) {
        values.push(applyOp(ops.pop(), values.pop(), values.pop()));
        System.out.println("ADDING to values: " + values.peek());
    }
    else {
        // Push current token to 'ops'.
        ops.push(tkn);
        System.out.println("ADDING to ops: " + ops.peek());
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM