Domanda

Il seguente classe è utilizzata da un altro programma. Quando si accede, si getta una StackOverflowError. Questo fa parte di un calcolatore di Postfix che devo fare come un progetto nella mia università.

Qualsiasi aiuto sarebbe molto apprezzato, grazie in anticipo. Sono abbastanza nuovo a Java e non ho idea di cosa fare.

codice:

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

}

È stato utile?

Soluzione

Il problema è che il class MyPostfixMachine ha un campo privato MyPostfixMachine mpm che viene inizializzato con un nuovo MyPostfixMachine . Dal momento che questa nuova MyPostfixMachine ha anche un campo MyPostfixMachine mpm privato che viene inizializzato con una nuova MyPostfixMachine ... lo si ottiene. :) Questo va avanti e per sempre (o fino a quando il tuo stack è pieno).

Questa è la parte problematica di codice:

public class MyPostfixMachine implements PostfixMachineInterface {

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

    // ...
}

Credo che si può semplicemente rimuovere il campo mpm privato. Basta chiamare i metodi sulla istanza corrente. Così, invece di:

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

si può semplicemente scrivere:

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

o (equivallent ma più esplicito):

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

In ogni caso, è sufficiente rimuovere il campo mpm privato e la StackOverflowException dovrebbe essere andato.

Altri suggerimenti

Non sono sicuro di come si sta ottenendo uno StackOverflowError (non vedo alcun loop o ricorsione in questo codice), ma un problema preciso è il vostro uso eccessivo di Queue.remove(). Ogni volta che si guarda la coda nelle clausole if, si sta tagliando-off il primo elemento -. Mi aspetto questo codice per essere NoSuchElementExceptions barfing-out

Per non parlare di tutte le EmptyStackExceptions si dovrebbe essere sempre da popping da un Stack vuota.

Quindi direi ....

  1. Esci chiamando `remove ()` quando si dovrebbe essere chiamando `peek ()`, invece.
  2. Esci spuntare da uno stack vuoto; si vuole essere tirando quei valori dalla coda di input, sì?
  3. Il problema dando il vostro `StackOverFlowError` è altrove. (Se non mi si affaccia qualcosa! - sempre possibile) Cercare un loop o una chiamata ricorsiva.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top