简体   繁体   中英

What causes this code to throw exception?

In some unsuccessful attempts to create a calculator in java that follows the BODMAS rule to solve complex mathematical expressions, I decided that it was important I create a method whose argument is a string. Such a method should detect braces and mathematical signs(ie plus , times , minus , divide , open and close brackets ) and should convert any string say temp that is between any two of the signs above into double say temp2 unless temp is empty(ie ""). The method then stores temp2 values and the signs in a list of Objects in the same order as in the argument. The method takes into consideration that if the first char is a number, then the first object to be placed in the list should be the double value of a substring of the argument from zero to the index of the first sign. The equivalent is done if the last char is a number at the last index of the list. The above idea led me to create the project below:

package maths.calculator;

import java.util.ArrayList;

public class NumGetter {
    static String expression;
    static ArrayList<Integer> preList = new ArrayList<>();
    static ArrayList<Object> list = new ArrayList<>();

    public static ArrayList<Object> getNumber(String num) {
        expression = num;
        try {
            if (expression == null) {
                expression = "";
            }
            if (expression == "") {
                return list;
            }

            int condition = 0;
            for (char chars : expression.toCharArray()) {
                if (chars == '-' || chars == '+' || chars == '÷' || chars == '×' || chars == ')' || chars == '(') {
                    preList.add(condition);
                }
                condition++;
            }

            if (preList.size() != 0) {
                System.out.println(preList);
                if (expression.charAt(0) >= '0' && expression.charAt(0) <= '9') {
                    String local = expression.substring(0, preList.get(0));
                    list.add(Double.parseDouble(local));
                }

                for (int i = 0; i < (preList.size() - 1); i++) {
                    int min = preList.get(i);
                    int next = preList.get(i + 1);
                    String local = expression.substring(min + 1, next);
                    if (local.length() == 0) {
                        list.add(expression.charAt(min));
                    } else {
                        double temp = Double.parseDouble(local);
                        list.add(expression.charAt(min));
                        list.add(temp);
                    }
                }
                if (expression.charAt(num.length() - 1) >= '0' && expression.charAt(num.length() - 1) <= '9') {
                    condition = preList.get(preList.size() - 1);
                    String local = expression.substring(condition);
                    list.add(expression.charAt(condition));
                    list.add(Double.parseDouble(local));
                }

            } else {
                list.add(Double.parseDouble(expression));
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
        return list;
    }

}

The code above looked satisfactory enough even after I imported the class above and called the method getNumber as shown below:

import java.util.ArrayList;

import maths.calculator.NumGetter;

public class Text {
    public static void main(String[] args) {

        System.out.println("(12+8)0");
        String one = "(12+8)0";
        ArrayList<Object> two = NumGetter.getNumber(one);
        System.out.println(two.toString());

    }
}

The problem lies in the output. In every case the Exception is thrown. Typically for the above, the out put was:

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 3 out of bounds for length 3
    at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
    at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
    at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
    at java.base/java.util.Objects.checkIndex(Objects.java:373)
    at java.base/java.util.ArrayList.get(ArrayList.java:425)
    at maths.calculator.NumGetter.getNumber(NumGetter.java:43)
    at demo.Text.main(Text.java:12)
(12+8)0
[0, 3, 5]

However when I change the iteration for (int i = 0; i < (preList.size() - 1); i++) to for (int i = 0; i < (preList.size() - 2); i++) , which by the way, should be incorrect, the result was quite close to the expected answer:

    at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2054)
    at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
    at java.base/java.lang.Double.parseDouble(Double.java:549)
    at maths.calculator.NumGetter.getNumber(NumGetter.java:51)
    at demo.Text.main(Text.java:12)
(12+8)0
[0, 3, 5]
[(, 12.0, )]

What possibly have gone wrong please... I very much need your good brains.

Following is the line throwing the exception java.lang.StringIndexOutOfBoundsException: String index out of range: -1 in the second iteration of the for loop:

String local = number.substring(++min, next); //line throwing exception

1st first iteration: number.substring(1, 1);

2nd iteration: number.substring(2, 1);

in the second iteration, it's throwing an exception because it's not allowed for the beginIndex of substring method to be greater than lastIndex. For more information please have a look here .

Thanks

At long last. I can't believe the last bug was in the last if block:

String local = expression.substring(condition);

I reckon it is supposed to be:

String local = expression.substring(condition+1);

Thanks to everyone especially @Andreas

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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