I have some code here for a calculator that I'm pretty sure should be working (I remember it working in the past), but it's acting up.
I've checked all the arrayList.get()
to make sure they're pointing to the right index, and there are the correct number of arrayList.remove()
's per loop.
The only other thing I can think of is that potentially the if
loop that checks if the result is a decimal or not (right down near the bottom of the method) is messing with things.
Here is the code:
public void onClickEquals (View view) {
TextView textViewError = (TextView) findViewById(R.id.textViewCalcPrevRes);
TextView textViewCalcPrevRes = (TextView) findViewById(R.id.textViewCalcPrevRes);
TextView textViewCalcCurrExp = (TextView) findViewById(R.id.textViewCalcCurrExp);
TextView textViewCalcPrevExp = (TextView) findViewById(R.id.textViewCalcPrevExp);
double calc = 0;
String calcOutputStr = "";
String tempString = "";
int c = arrayList.size();
try {
textViewError.setText("");
//i.e. array [2,+,3,*,4,-,3] size(c) = 7, so [2,+,3,*,4,-,3]
while (c != 1) {
if (c > 3) {
if (arrayList.get(3).contains("×") || arrayList.get(3).contains("÷")) {
if (arrayList.get(3).contains("×")) {calc = Double.parseDouble(arrayList.get(2)) * Double.parseDouble(arrayList.get(4));}
if (arrayList.get(3).contains("÷")) {calc = Double.parseDouble(arrayList.get(2)) / Double.parseDouble(arrayList.get(4));}
//calc = 12 ;array = [2,+,3,*,4,-,3]
arrayList.remove(2); //[2,+,*,4,-,3]
arrayList.remove(2); //[2,+,4,-,3]
arrayList.remove(2); //[2,+,-,3]
arrayList.add(2, Double.toString(calc)); //[2,+,12,-,3]
c = arrayList.size(); // size(c) = 5
} else {
//[2,+,12,-,3]
if (arrayList.get(1).contains("+")) {calc = Double.parseDouble(arrayList.get(0)) + Double.parseDouble(arrayList.get(2));}
if (arrayList.get(1).contains("-")) {calc = Double.parseDouble(arrayList.get(0)) - Double.parseDouble(arrayList.get(2));}
if (arrayList.get(1).contains("×")) {calc = Double.parseDouble(arrayList.get(0)) * Double.parseDouble(arrayList.get(2));}
if (arrayList.get(1).contains("÷")) {calc = Double.parseDouble(arrayList.get(0)) / Double.parseDouble(arrayList.get(2));}
//calc = 14
arrayList.remove(0); //[+,12,-,3]
arrayList.remove(0); //[12,-,3]
arrayList.remove(0); //[-,3]
arrayList.add(0, Double.toString(calc)); //[14,-,3]
c = arrayList.size(); // size(c) = 3
}
}
// size(c) <= 3
else {
if (arrayList.get(1).contains("+")) {calc = Double.parseDouble(arrayList.get(0)) + Double.parseDouble(arrayList.get(2));}
if (arrayList.get(1).contains("-")) {calc = Double.parseDouble(arrayList.get(0)) - Double.parseDouble(arrayList.get(2));}
if (arrayList.get(1).contains("×")) {calc = Double.parseDouble(arrayList.get(0)) * Double.parseDouble(arrayList.get(2));}
if (arrayList.get(1).contains("÷")) {calc = Double.parseDouble(arrayList.get(0)) / Double.parseDouble(arrayList.get(2));}
//calc = 11
arrayList.remove(0); //[-,3]
arrayList.remove(0); //[3]
arrayList.remove(0); //[null]
arrayList.add(0, Double.toString(calc)); // [9]
c = arrayList.size(); // size(c) = 1
prevCalc = Double.toString(calc);
}
//CHECK IF DECIMAL - SHOULD BE OUTSIDE WHILE LOOP
//check if calc is a whole number; if yes, convert to string and enter into tempString, remove decimal and enter into calcOutputStr ready for display on screen.
if (calc % 1 == 0) {
tempString = Double.toString(calc);
if (tempString != null) {
tempString = tempString.substring(0, tempString.length() - 2);
}
calcOutputStr = tempString;
arrayList.clear();
}
//if calc is a decimal convert to string ready for display on screen.
else {
calcOutputStr = Double.toString(calc);
arrayList.clear();
}
}
textViewCalcPrevExp.setText(textViewCalcCurrExp.getText()); //copy text from textViewCalcCurrExp to textViewCalcPrevExp
textViewCalcCurrExp.setText(""); //remove text from textViewCalcCurrExp
textViewCalcPrevRes.setText(calcOutputStr); //display calc
stringInput = "";
stringInputWithOp="";
}
catch (Exception e) {
e.printStackTrace();
textViewCalcPrevExp.setText(textViewCalcCurrExp.getText());
textViewCalcCurrExp.setText("");
stringInput="";
stringInputWithOp="";
arrayList.clear();
textViewError.setText("ERROR");
}
}
I'll give two scenarios to help illustrate my issue:
arrayList = [2,+,2];
upon running this method,textViewCalcPrevRes
displays4
arrayList = [2,+,2,+,2];
upon running this method,textViewCalcPrevRes
displaysERROR
, due to the method throwing an exception and printing the stack trace in the console (see next code block). The really weird thing is that thecatch{}
statement should outputERROR
totextViewError
and nottextViewCalcPrevRes
.
Here's the stack trace outputted to the console in scenario 2:
W/System.err: java.lang.IndexOutOfBoundsException: Index: 1, Size: 0
W/System.err: at java.util.ArrayList.get(ArrayList.java:411)
W/System.err: at com.st1.u3141294.sparkscientificcalculator.sparkMain$override.onClickEquals(sparkMain.java:126)
W/System.err: at com.st1.u3141294.sparkscientificcalculator.sparkMain$override.access$dispatch(sparkMain.java)
W/System.err: at com.st1.u3141294.sparkscientificcalculator.sparkMain.onClickEquals(sparkMain.java:0)
W/System.err: at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)
W/System.err: at android.view.View.performClick(View.java:5610)
W/System.err: at android.view.View$PerformClick.run(View.java:22260)
W/System.err: at android.os.Handler.handleCallback(Handler.java:751)
W/System.err: at android.os.Handler.dispatchMessage(Handler.java:95)
W/System.err: at android.os.Looper.loop(Looper.java:154)
W/System.err: at android.app.ActivityThread.main(ActivityThread.java:6077)
W/System.err: at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Obviously it's throwing an IndexOutOfBounds Exception, however I'm really not sure how/why.
Any ideas please?
EDIT: Further "investigation" suggests that the origin of the exception is from this line of code (marked with //-->
):
// size(c) <= 3
else {
//-->if (arrayList.get(1).contains("+")) {calc = Double.parseDouble(arrayList.get(0)) + Double.parseDouble(arrayList.get(2));}
if (arrayList.get(1).contains("-")) {calc = Double.parseDouble(arrayList.get(0)) - Double.parseDouble(arrayList.get(2));}
if (arrayList.get(1).contains("×")) {calc = Double.parseDouble(arrayList.get(0)) * Double.parseDouble(arrayList.get(2));}
if (arrayList.get(1).contains("÷")) {calc = Double.parseDouble(arrayList.get(0)) / Double.parseDouble(arrayList.get(2));}
EDIT: @Code-Apprentice:
If we use scenario 2 as the contents of the arrayList
(that is [2,+,2,+,2]
), then my code should work. Following the trace:
First block of code run because c = arrayList.size() = 5
, and there are no multiplication/division operators in the arrayList
, so it would go to the else
loop:
while (c != 1) {
if (c > 3) {
//here is code only run if there are multiplication or division operators in arrayList
} else {
if (arrayList.get(1).contains("+")) {calc = Double.parseDouble(arrayList.get(0)) + Double.parseDouble(arrayList.get(2));}
}
arrayList.remove(0); //bringing arrayList down to [+,2,+,2]
arrayList.remove(0); //then [2,+,2]
arrayList.remove(0); //then [+,2]
arrayList.add(0, Double.toString(calc)); //then adding 4 (calc) to arrayList[0] would give [4,+,2]
c = arrayList.size(); // therefore arrayList.size() = 3
}
Now, since c = arrayList.size() = 3
:
// size(c) <= 3
else {
//4+2
if (arrayList.get(1).contains("+")) {calc = Double.parseDouble(arrayList.get(0)) + Double.parseDouble(arrayList.get(2));}
}
//new value of calc = 6
arrayList.remove(0); //gives [+,2]
arrayList.remove(0); //gives [2]
arrayList.remove(0); //arrayList is now empty: [null]
arrayList.add(0, Double.toString(calc)); // arrayList populated with calc --> [6]
c = arrayList.size(); // size(c) = 1
prevCalc = Double.toString(calc); //puts this calculation into memory for next calculation if needed