StackOverFlowError в постфиксном калькуляторе Java
-
19-09-2019 - |
Вопрос
Следующий класс используется другой программой.При доступе к нему выдается StackOverFlowError.Это часть калькулятора Postfix, который мне нужно сделать в рамках проекта в моем университете.
Любая помощь будет принята с благодарностью, заранее спасибо.Я новичок в Java и понятия не имею, что делать.
КОД:
import java.util.Queue;
import java.util.Stack;
public class MyPostfixMachine implements PostfixMachineInterface {
MyMathOperations mmo = new MyMathOperations();
MyPostfixMachine mpm = new MyPostfixMachine();
public String evaluate(Queue q) {
if (q.isEmpty()) {//if the input is empty, terminate the program
System.exit(0);
}
if (q.size() == 1) {//if there is only one number in the queue, return it as the solution
if (mpm.isParsableToDouble(String.valueOf(q.remove()))) {
return String.valueOf(q.remove());
}
}
Stack<String> finalxp = new Stack<String>();//create an empty stack
if (mpm.isParsableToDouble(String.valueOf(q.remove()))) {//if first element of queue q is a number,push it into the stack
finalxp.push(String.valueOf(q.remove()));
} else {//depending on the operator perform the corresponding operations
if (q.remove() == "+") {
String str = String.valueOf(finalxp.pop());
String str2 = String.valueOf(finalxp.pop());
finalxp.push(mmo.addition(str, str2));
}
if (q.remove() == "-") {
String str = String.valueOf(finalxp.pop());
String str2 = String.valueOf(finalxp.pop());
finalxp.push(mmo.substraction(str, str2));
}
if (q.remove() == "*") {
String str = String.valueOf(finalxp.pop());
String str2 = String.valueOf(finalxp.pop());
finalxp.push(mmo.product(str, str2));
}
if (q.remove() == "/") {
String str = String.valueOf(finalxp.pop());
String str2 = String.valueOf(finalxp.pop());
finalxp.push(mmo.division(str, str2));
}
if (q.remove() == "fibo") {
String str = String.valueOf(finalxp.pop());
finalxp.push(mmo.fibonacci(str));
}
if (q.remove() == "fac") {
String str = String.valueOf(finalxp.pop());
finalxp.push(mmo.factorial(str));
}
if (q.remove() == "han") {
String str = String.valueOf(finalxp.pop());
finalxp.push(mmo.hanoi(str));
}
}
return String.valueOf(finalxp.pop());
}
public boolean isParsableToDouble(String candidate) {
try {
Double.parseDouble(candidate);
return true;
} catch (NumberFormatException nfe) {
return false;
}
}
}
public class MyMathOperations implements MathOperationsInterface {
public String addition(String s1, String s2) {
double A = Double.parseDouble(s1);
double B = Double.parseDouble(s2);
return String.valueOf((A + B));
}
public String substraction(String s1, String s2) {
double A = Double.parseDouble(s1);
double B = Double.parseDouble(s2);
return String.valueOf((A - B));
}
public String product(String s1, String s2) {
double A = Double.parseDouble(s1);
double B = Double.parseDouble(s2);
return String.valueOf((A * B));
}
public String division(String s1, String s2) {
double A = Double.parseDouble(s1);
double B = Double.parseDouble(s2);
return String.valueOf((A / B));
}
public String fibonacci(String s) {
int n = Integer.parseInt(s);
return String.valueOf(fibo(n));
}
public int fibo(int f) {
if (f < 0) {
throw new IllegalArgumentException("Cannot apply Fibonacci method");
} else if (f == 0) {
return 0;
} else if (f == 1) {
return 1;
} else {
return fibo(f - 1) + fibo(f - 2);
}
}
public String hanoi(String s) {
int a = Integer.parseInt(s);
int han = 0;
if (a < 0) {
throw new IllegalArgumentException("Not a valid integer");
} else {
han = (int) Math.pow(2, a) - 1;
}
return String.valueOf(han);
}
public String factorial(String s) {
int a = Integer.parseInt(s);
if (a < 0) {
throw new IllegalArgumentException("Incorrect argument for factorial operatiion");
}
switch (a) {
case 0:
case 1:
return String.valueOf(1);
default:
int res = a;
while (true) {
if (a == 1) {
break;
}
res *= --a;
}
return String.valueOf(res);
}
}
private static double pDouble(String s) {
double res = 0d;
try {
res = Double.parseDouble(s);
} catch (NumberFormatException e) {
System.exit(1);
}
return res;
}
}
Решение
Проблема в том, что ваш класс MyPostfixMachine имеет личное поле MyPostfixMachine мпм который инициализируется с помощью новый MyPostfixMachine.Поскольку этот новый MyPostfixMachine также имеет частное поле MyPostfixMachine mpm, которое инициализируется новым MyPostfixMachine...ты понял.:) Это продолжается и продолжается вечно (или пока ваш стек не заполнится).
Вот проблемный фрагмент кода:
public class MyPostfixMachine implements PostfixMachineInterface {
MyMathOperations mmo = new MyMathOperations();
MyPostfixMachine mpm = new MyPostfixMachine(); // problem is here
// ...
}
Я думаю, вы можете просто удалить частное поле mpm.Просто вызовите методы текущего экземпляра.Итак, вместо:
if (mpm.isParsableToDouble(String.valueOf(q.remove()))) {...}
вы можете просто написать:
if (isParsableToDouble(String.valueOf(q.remove()))) {...}
или (эквивалентно, но более явно):
if (this.isParsableToDouble(String.valueOf(q.remove()))) {...}
В любом случае, просто удалите частное поле mpm, и исключение StackOverflowException должно исчезнуть.
Другие советы
Я не уверен, как вы получаете StackOverflowError (я не вижу в этом коде никаких циклов или рекурсии), но одна определенная проблема — это чрезмерное использование вами Queue.remove()
.Каждый раз, когда вы смотрите на очередь в своем if
предложений, вы отсекаете первый элемент - я ожидаю, что этот код будет блевать NoSuchElementException
с.
Не говоря уже обо всем EmptyStackException
это вы должны получить, выскочив из пустого Stack
.
Так что я бы сказал....
- Прекратите вызывать `remove()`, когда вместо этого вам следует вызывать `peek()`.
- Перестаньте извлекать данные из пустой стопки;вы хотите получать эти значения из очереди ввода, да?
- Проблема, выдающая вам StackOverFlowError, заключается в другом месте.(Если я что-то не упускаю из виду — всегда возможно!) Ищите цикл или рекурсивный вызов.