Question

La classe suivante est utilisée par un autre programme. Quand il est accessible, il jette un StackOverflowError. Cela fait partie d'une calculatrice Postfix je dois faire comme un projet à mon université.

Toute aide serait grandement appréciée, je vous remercie à l'avance. Je suis tout à fait nouveau à Java et je ne sais pas quoi faire.

CODE:

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

}

Était-ce utile?

La solution

Le problème est que votre classe MyPostfixMachine a un champ privé MyPostfixMachine mpm qui est initialisé avec nouvelle MyPostfixMachine . Depuis cette nouvelle MyPostfixMachine dispose également d'un domaine privé MyPostfixMachine mpm qui est initialisé avec une nouvelle MyPostfixMachine ... vous l'obtenez. :) Ce qui se passe et pour toujours (ou jusqu'à ce que votre pile est pleine).

Voici la pièce problématique de code:

public class MyPostfixMachine implements PostfixMachineInterface {

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

    // ...
}

Je pense que vous pouvez simplement supprimer le champ privé mpm. Il suffit d'appeler les méthodes de l'instance actuelle. Ainsi, au lieu de:

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

vous pouvez simplement écrire:

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

ou (équivallent mais plus explicite):

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

De toute façon, il suffit de supprimer le domaine privé mpm et le StackOverflowException devrait disparaître.

Autres conseils

Je ne sais pas comment vous obtenez un StackOverflowError (je ne vois pas de boucles ou récursion dans ce code), mais un problème défini est votre utilisation excessive de Queue.remove(). Chaque fois que vous regardez la file d'attente dans vos clauses de if, vous êtes ébranchage-off le premier élément -. Je pense que ce code soit barfing-out NoSuchElementExceptions

Pour ne rien dire de tous les EmptyStackExceptions vous devriez obtenir de sauter d'un Stack vide.

Je dirais ....

  1. Quitter appeler `remove ()` quand vous devriez appellerez `peek ()` à la place.
  2. Quitter sauter à partir d'une pile vide; vous voulez être tirer ces valeurs de votre file d'attente d'entrée, oui?
  3. Le problème que vous donner votre `StackOverFlowError` est ailleurs. (À moins que je suis sur quelque chose - toujours possible) Recherchez une boucle ou un appel récursif.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top