Pregunta

La siguiente clase es utilizado por otro programa. Cuando se accede a ella, se lanza una StackOverflowError. Esto es parte de una calculadora de Postfix que tengo que hacer como un proyecto en mi universidad.

Cualquier ayuda sería muy apreciada, gracias de antemano. Soy bastante nuevo en Java y no tengo ni idea de qué hacer.

CÓDIGO:

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;
}

}

¿Fue útil?

Solución

El problema es que su clase MyPostfixMachine tiene un campo privado MyPostfixMachine mpm que se inicializa con un nueva MyPostfixMachine . Desde esta nueva MyPostfixMachine también tiene un mpm MyPostfixMachine ámbito privado, que se inicia con un nuevo MyPostfixMachine ... que conseguirlo. :) Esto sigue y sigue para siempre (o hasta que la pila está llena).

Aquí está la pieza problemática de código:

public class MyPostfixMachine implements PostfixMachineInterface {

    MyMathOperations mmo = new MyMathOperations();
    MyPostfixMachine mpm = new MyPostfixMachine(); // problem is here

    // ...
}

Creo que se puede simplemente eliminar el mpm ámbito privado. Sólo tiene que llamar a los métodos en la instancia actual. Así que en lugar de:

if (mpm.isParsableToDouble(String.valueOf(q.remove()))) {...}

simplemente hay que escribir:

if (isParsableToDouble(String.valueOf(q.remove()))) {...}

o (equivallent pero más explícito):

if (this.isParsableToDouble(String.valueOf(q.remove()))) {...}

De todos modos, basta con retirar el mpm ámbito privado y el StackOverflowException debe desaparecer.

Otros consejos

No estoy seguro de cómo le está dando una StackOverflowError (no veo ningún bucles o la recursión en el código), pero un problema definido es el uso excesivo de Queue.remove(). Cada vez que nos fijamos en la cola en sus cláusulas if, estás lopping-off el primer elemento -. Yo esperaría que este código sea NoSuchElementExceptions barfing-out

Para no hablar de todos los EmptyStackExceptions que debería estar recibiendo desde hace estallar de un Stack vacía.

Así que diría ....

  1. Dejar de llamar `remove ()` cuando debería estar llamando `peek ()` en lugar.
  2. Salir apareciendo a partir de una pila vacía; desea estar tirando esos valores de la cola de entrada, sí?
  3. El problema que le da su `StackOverFlowError` está en otra parte. (A menos que esté pasando por alto algo - siempre es posible) Busque un bucle o una llamada recursiva.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top