SlandShow
@SlandShow
70% of my body is made of movies.

Почему stack оказывается пустым?

Доброго времени суток.

Сразу о главном. У меня есть код:
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Toast;

import java.util.Scanner;
import java.util.Stack;

/**
 * Created by Admin on 02.12.2017.
 */

class PostfixCalculator extends AppCompatActivity{

    private Stack<String> stack;
    private String regular;
    private double result;

    public PostfixCalculator(String regular) {
        this.regular = regular;
        stack = new Stack<>();

        // Parse and calculate
        parse(regular);
    }

    public PostfixCalculator() {
        stack = new Stack<>();
    }

    public void startCalculate(String regular) {
        this.regular = regular;
        parse(regular);
    }

    private void parse(String s) {
        String currentElement = "";
        String[] elements = s.split(" ");
        double number1, number2, interAns = 0;

        for (int i = 0; i < elements.length; i++) {
            currentElement = elements[i];

           
            // Check if current element is number
            try {
                double element = Double.parseDouble(currentElement);
                stack.push(String.valueOf(element));
            } catch (NumberFormatException e) {
                if (!currentElement.equals("") ) {

                        number2 = Double.valueOf(stack.pop());
                        number1 = Double.valueOf(stack.pop());


            new Scanner(System.in);
                    // Make calculations
                    if (currentElement.equals("+"))
                        interAns = number1 + number2;
                    else if (currentElement.equals("-"))
                        interAns = number1 - number2;
                    else if (currentElement.equals("×"))
                        interAns = number1 * number2;
                    else if (currentElement.equals("/"))
                        interAns = number1 / number2;
                    else interAns = 0;

                    stack.push(String.valueOf(interAns));
                }
            }
            Log.d("DEB-A", "" + interAns);
        }
        interAns = Double.valueOf(stack.pop());
        result = interAns;
    }


    public double getResult() {
        return result;
    }

}


Объекту этого класса подаётся постфиксная строка выражения с пробелами (вроде 12 5 2 * - и он считает выражение с помощью стека).
Он парсит постфиксную запись и считает выражение. Но, у меня происходит ошибка:
E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.example.admin.calculater, PID: 4147
                  java.lang.IllegalStateException: Could not execute method for android:onClick
                      at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:293)
                      at android.view.View.performClick(View.java:5198)
                      at android.view.View$PerformClick.run(View.java:21147)
                      at android.os.Handler.handleCallback(Handler.java:739)
                      at android.os.Handler.dispatchMessage(Handler.java:95)
                      at android.os.Looper.loop(Looper.java:148)
                      at android.app.ActivityThread.main(ActivityThread.java:5417)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
                   Caused by: java.lang.reflect.InvocationTargetException
                      at java.lang.reflect.Method.invoke(Native Method)
                      at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)
                      at android.view.View.performClick(View.java:5198) 
                      at android.view.View$PerformClick.run(View.java:21147) 
                      at android.os.Handler.handleCallback(Handler.java:739) 
                      at android.os.Handler.dispatchMessage(Handler.java:95) 
                      at android.os.Looper.loop(Looper.java:148) 
                      at android.app.ActivityThread.main(ActivityThread.java:5417) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
                   Caused by: java.util.EmptyStackException
                      at java.util.Stack.pop(Stack.java:73)
                      at com.example.admin.calculater.PostfixCalculator.parse(PostfixCalculator.java:53)
                      at com.example.admin.calculater.PostfixCalculator.startCalculate(PostfixCalculator.java:33)
                      at com.example.admin.calculater.CalculaterActivity.onClickEqual(CalculaterActivity.java:188)
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288) 
                      at android.view.View.performClick(View.java:5198) 
                      at android.view.View$PerformClick.run(View.java:21147) 
                      at android.os.Handler.handleCallback(Handler.java:739) 
                      at android.os.Handler.dispatchMessage(Handler.java:95) 
                      at android.os.Looper.loop(Looper.java:148) 
                      at android.app.ActivityThread.main(ActivityThread.java:5417) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 


Выходит, что ошибка в стеке:
number2 = Double.valueOf(stack.pop());
                        number1 = Double.valueOf(stack.pop());


Но я никак не могу понять, я же точно такой же код уже писал на обычной Java и всё работало! Я даже ссылку оставлю на Online IDE.

Как док-во:
5a28395b8fb34255012585.pngВ общем, я так и не понял, почему это происходит?

Вот тут аналогичный код на обычно Java, можно само...
  • Вопрос задан
  • 189 просмотров
Решения вопроса 1
SlandShow
@SlandShow Автор вопроса
70% of my body is made of movies.
Ошибка была в неправильном парсинге постфиксной нотации. У меня сначала была проверка на то, что итерируемый элемент - число, а стоило мне поменять местами эти проверки (сначала проверяю итерируемый элемент на оператор) - всё заработало.

Вот незначительная правка кода:
private void parse() {
        String currentElement = "";
        String[] elements = regular.split(" ");
        double number1, number2, interAns;

        for (int i = 0; i < elements.length; i++) {
            currentElement = elements[i];

            // Check if current element is operator
          	if (isOperator(currentElement)) {
              	if (stack.size() > 1 && !currentElement.equals("")) {
                  	 number2 = stack.pop();
                   	 number1 = stack.pop();

                   	 // Make calculations
                   	 if (currentElement.equals("+"))
                        interAns = number1 + number2;
                   	 else if (currentElement.equals("-"))
                        interAns = number1 - number2;
                  	 else if (currentElement.equals("*"))
                        interAns = number1 * number2;
                   	 else if (currentElement.equals("/"))
                        interAns = number1 / number2;
                   	 else interAns = 0;

                    stack.push(interAns);
                }
            } else {
              	try {
               		double element = Double.parseDouble(currentElement);
                	stack.push(element);
                } catch (NumberFormatException e) {
                  	System.out.println("Hmm...");
                }
            }
          
          
          /*
            try {
                double element = Double.parseDouble(currentElement);
                stack.push(element);
            } catch (NumberFormatException e) {
                if (!currentElement.equals("")) {
                    number2 = stack.pop();
                    number1 = stack.pop();

                    // Make calculations
                    if (currentElement.equals("+"))
                        interAns = number1 + number2;
                    else if (currentElement.equals("-"))
                        interAns = number1 - number2;
                    else if (currentElement.equals("*"))
                        interAns = number1 * number2;
                    else if (currentElement.equals("/"))
                        interAns = number1 / number2;
                    else interAns = 0;

                    stack.push(interAns);
                }
            }*/
        }
        interAns = stack.pop();
        result = interAns;
    }

// Новая функция
private boolean isOperator(String s) {
        return s.equals("+")|| s.equals("-") || s.equals("*") || s.equals("/");
}


Раньше мой код не мог парсить вот такие выражения: infix: 12 - 5 * 2 + 16 / 4 - 50 / 10 (postfix is 12 5 2 * - 16 4 / + 50 10 / -) - не совсем понимаю почему, но стоило мне поменять местами сравнения, так всё сразу заработало!

5a2919e977bb5940625141.png

Ну и ещё стоит отметить то, как отметил Денис Загаевский , что надо добавить доп.проверку на пустоту стека ( if (stack.size() > 1) ...).
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@Tiberal
Если в чистой жаве работает, то может дело в
Could not execute method for android:onClick
?
Ответ написан
zagayevskiy
@zagayevskiy Куратор тега Java
Android developer at Yandex
Очень интересно, как именно это происходит. Кто варварски зовёт публичный метод у активити? В андроиде так не делают. Это раз. Дальше, когда вы напарываетесь на намберформат, никаких проверок нет, просто достаёте из стека два элемента. Надо смотреть. Возможно, дебаггером.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы