Оценить значение арифметического выражения в обратной польской нотации

нам дан массив String, содержащий постфиксное выражение в качестве его элементов, и нам нужно выполнить оценку

я пробовал это с помощью стека, но столкнулся с исключением: Исключение в потоке "основной" java.util.EmptyStackException

public int evalRPN(String[] A) {

     Stack<Integer> s=new Stack<>();
     int i=0;
     while(s.isEmpty()==false && i<A.length)
     {
        String p=A[i++];
        if(p.matches("\\d"))
            s.push(Integer.parseInt(p));
        else
            {
                int a=s.pop();
                int b=s.pop();

                switch(p)
                {
                    case "+": s.push(b+a);break;
                    case "-": s.push(b-a);break;
                    case "*": s.push(b*a);break;
                    case "/": s.push(b/a);break;


                }
            }

    }
    return s.pop();
 }

person Community    schedule 13.09.2019    source источник
comment
Можете ли вы привести пример ввода, который вы вводите, что приводит к исключению?   -  person Kevin DiTraglia    schedule 14.09.2019
comment
A: [ 4, 13, 5, /, + ], но используйте do while, так как мой цикл никогда не выполняется   -  person    schedule 14.09.2019
comment
Вам нужны два стека.   -  person Elliott Frisch    schedule 14.09.2019
comment
@ElliottFrisch Вам нужен только один стек для оценки постфиксного выражения. Вам нужно два стека, если вы хотите оценить инфиксное выражение.   -  person Jim Mischel    schedule 16.09.2019
comment
s.isEmpty()==false — ваш только что созданный стек пуст, поэтому этот код никогда не запустится.   -  person Johannes Kuhn    schedule 16.09.2019


Ответы (2)


public int evalRPN(String[] A) {

     Stack<Integer> s=new Stack<>();
     int i=0;
     while(i<A.length) //stack will be empty right at the start.. no need to check this
     {
        String p=A[i++];
        if(p.matches("\\d")) //I am not quite sure, but this just matches single digits, right? I would go for "\\d*", but I am not completely sure. Anyways you won't capture negative values or decimals.. perhaps better exclude +-*/ and use Double.parseDouble and a Stack<Double>
            s.push(Integer.parseInt(p));
        else
            {
                int a=s.pop();
                int b=s.pop();

                switch(p)
                {
                    case "+": s.push(b+a);break;
                    case "-": s.push(b-a);break;
                    case "*": s.push(b*a);break;
                    case "/": s.push(b/a);break;


                }
            }

    }
    return s.pop();
 }

Это может привести к ошибке, если данное выражение неверно (слишком много операторов/слишком мало операндов) или может вернуть только промежуточный результат (слишком много операндов/слишком мало операторов).

person Islingre    schedule 13.09.2019
comment
Я бы предложил p.matches("-?\\d+") и default с сообщением об ошибке, так как "13" действительно не повезло. - person Joop Eggen; 16.09.2019

В вашем коде есть несколько проблем. Я добавил комментарии, чтобы описать их.

public int evalRPN(String[] A) {

     Stack<Integer> s=new Stack<>();
     int i=0;

     // The stack will be empty on entry, so this loop is never executed.
     // You should change this to while (i < A.length)
     while(s.isEmpty()==false && i<A.length)
     {
        String p=A[i++];

        // This only matches a single digit. So something like "1X" would be
        // accepted. That will cause an error in the call to parseInt().
        // If you care about detecting invalid input, you'll have to handle
        // the exception, or find another way to do this.
        if(p.matches("\\d"))
            s.push(Integer.parseInt(p));
        else
            {
                int a=s.pop();
                int b=s.pop();

                switch(p)
                {
                    case "+": s.push(b+a);break;
                    case "-": s.push(b-a);break;
                    case "*": s.push(b*a);break;
                    case "/": s.push(b/a);break;
                    // You have no default case here, so the program will
                    // just ignore anything that is not, '+','-','*','/'
                }
            }

    }

    // Here, you should verify that s contains just one value. If s is empty,
    // or if s has 2 or more values, then the input was not a valid postfix
    // expression.
    return s.pop();
 }
person Jim Mischel    schedule 16.09.2019
comment
Приятно оставить работу / размышления ОП, так как это явно домашняя работа. - person Joop Eggen; 16.09.2019