Проблемы с первой Java-программой (калькулятором) - PullRequest
0 голосов
/ 24 января 2009

Я нахожусь в процессе изучения Java, и мой первый проект - калькулятор, однако я столкнулся с проблемой. Я пытаюсь заставить свой калькулятор позволить мне ввести число, затем щелкнуть по оператору (+, -, x, /), ввести другой номер, затем снова нажать оператор и получить обновление дисплея и иметь возможность продолжать работу.

Например, я хотел бы иметь возможность нажимать следующее и отображать общее количество каждый раз, когда я нажимаю на оператора после первого:

a + b / c - d =

Код, который у меня есть (мне кажется), должен работать, но это не так. Что я делаю не так?

Ниже приведен код, который я использую, когда вы нажимаете на оператора. По умолчанию ожидание установлено на false. После однократного прохождения через класс значение1 сохраняется, а ожидание устанавливается в значение true, и это прекрасно работает. Оттуда это, кажется, не работает совершенно правильно:

class OperatorListener implements ActionListener {
    public void actionPerformed(ActionEvent event) {
        String input = event.getActionCommand();

        // Set display as string
        String s = display.getText();

        if (!wait) {
            // Convert first input string to double
            try {
                value1 = Double.valueOf(s.trim()).doubleValue();
            } catch (NumberFormatException nfe) {
                System.out.println("NumberFormatException: " + nfe.getMessage());
            }

            dec = false;
        } else {
            // Convert second input string to double
            try {
                value2 = Double.valueOf(s.trim()).doubleValue();
            } catch (NumberFormatException nfe) {
                System.out.println("NumberFormatException: " + nfe.getMessage());
            }

            // Determine operation to be performed
            if (operator == "add") {
                value1 = Operators.add(value1, value2);             
            } else if (operator == "subtract") {
                value1 = Operators.subtract(value1, value2);
            } else if (operator == "multiply") {
                value1 = Operators.multiply(value1, value2);
            } else if (operator == "divide") {
                value1 = Operators.divide(value1, value2);
            }

            // Convert final value to string and display
            display.setText(Double.toString(value1));

            dec = false;
        }

        // Determine operator hit
        if (input.equals("+")) {
            operator = "add";
        } else if (input.equals("-")) {
            operator = "subtract";
        } else if (input.equals("x")) {
            operator = "multiply";
        } else if (input.equals("/")) {
            operator = "divide";
        }

        // Set wait
        wait = true;

    }
}

РЕДАКТИРОВАТЬ: Обновлен код, чтобы исправить некоторую путаницу и обновить оператор if. Даже после этого та же проблема все еще существует. Также полный исходный код доступен здесь

Ответы [ 5 ]

4 голосов
/ 24 января 2009

Несколько предложений.

Во-первых, я бы предложил при использовании boolean в качестве условия для оператора if избегать сравнения с true и false - в любом случае для boolean существует только два состояния. Кроме того, поскольку существует только два состояния, вместо использования else if (false), достаточно else:

if (condition == true)
{
  // when condition is true 
}
else if (condition == false)
{
  // when condition is false
}

можно переписать как:

if (condition)
{
  // when condition is true 
}
else
{
  // when condition is false
}

Во-вторых, вместо сравнения строковых литералов "add", "subtract" и т. Д. Попробуйте использовать константы (final переменные) или enum с. Выполнение сравнения String, такого как (operator == "add"), выполняет проверку, чтобы определить, являются ли строковый литерал "add" и переменная operator ссылкой на один и тот же объект, а не значения одинаковы. Таким образом, при определенных обстоятельствах вы можете установить operator на "add", но сравнение может не быть true, потому что строковый литерал ссылается на отдельный объект. Простой обходной путь будет:

final String operatorAdd = "add";
// ...

if (input.equals("+"))
  operator = operatorAdd;
  // ...

if (operator == operatorAdd)
  // ...

Теперь и присвоение operator, и сравнение operator оба ссылаются на константу operatorAdd, поэтому для сравнения можно использовать ==, а не equals() метод.

В-третьих, поскольку это похоже на калькулятор, который на самом деле не требует двух операндов (например, operand1 + operand2), а, скорее, одного операнда, который действует на сохраненное значение (то есть operand + currentValue), он, вероятно, было бы проще иметь некоторую переменную, которая содержит текущее значение, и другую переменную, которая содержит оператор, и метод, который будет действовать в соответствии с текущим оператором и операндом. (Более или менее идея аккумуляторной машины или компьютера с 1 операндом.)

Основной метод работы будет:

  1. Установите currentValue.
  2. Установите оператора.
  3. Установите operand.
  4. Выполнить расчет.
  5. Установить currentValue на результат расчета.
  6. Установить оператор в пустое состояние.

Каждый шаг должен проверять, был ли выполнен предыдущий шаг - убедитесь, что указана операция (для operator установлен допустимый оператор), затем следующее введенное значение становится operand. Калькулятор похож на конечный автомат , где переход от одного шага к другому должен выполняться в определенном порядке, иначе он не перейдет к следующему шагу.

Итак, калькулятор может быть таким (псевдокод!):

// Initialize calculator (Step 1)
currentValue = 0;
operand = 0;
operator = operatorNone;

loop 
{
  operand = getOperand();     // Step 2
  operator = getOperator();   // Step 3

  // Step 4 and 5
  if (operator == operatorAdd)
    currentValue += operand;
  if (operator == operatorSubtract)
    currentValue -= operand;
  // ...

  // Step 6
  operator = operatorNone;
}

Хотя в приведенном выше коде используется один цикл и он не работает как модель графического интерфейса пользователя на основе событий, но в нем должны быть указаны шаги, необходимые для запуска калькулятора.

3 голосов
/ 24 января 2009

Каждый раз, когда вы вводите оператор, ваш код будет выполнять это:

Double.valueOf(s.trim())

для установки value1 или value2 (в зависимости от wait). Это вызовет исключение, потому что операторы не могут быть проанализированы как двойные. Возможно, вам лучше будет проверить оператора сначала , прежде чем пытаться проанализировать ввод как число. Тогда, если это был оператор, вы можете пропустить часть анализа номера.

Также подумайте о том, что может произойти, если кто-то введет два числа или два оператора подряд.

1 голос
/ 24 января 2009

Как сказал Грег, независимо от того, что вводит, и независимо от текущего состояния программы, вы всегда анализируете число. Вам нужно более четко отслеживать состояние программы. Я предполагаю, что когда у вас есть код "String s = output.getText ();" что вы действительно имеете в виду "String s = input.getText ();".

Также обратите внимание, что

  if (wait == false) {
    // Stuff for !wait
  } else if (wait == true) {
    // Stuff for wait
  }

излишне избыточен. Вы можете заменить его на:

  if (!wait) {
    // Stuff for !wait
  } else {
    // Stuff for wait
  }

Вам, вероятно, следует сначала проверить строку ввода, чтобы узнать, является ли она оператором, а если нет, то убедитесь, что она числовая. Написание калькулятора infix (который правильно обрабатывает приоритет) не тривиально.

0 голосов
/ 25 января 2009

После поиска по максимуму и минимуму я наконец решил, что проблема не в коде, который я предоставил. У меня было "wait = false;" в моем классе NumberListener, который испортил выполнение. Чтобы решить эту проблему, я создал 2 отдельные переменные ожидания, и пока все работает нормально.

Спасибо за помощь и советы, ребята, +1 всем вам за попытку.

0 голосов
/ 24 января 2009

Вы можете использовать скриптовый движок в Java. Если у вас нет Java 6+, вы можете использовать Rhino, который делает то же самое. Затем вы можете делать практически все, что можете в JavaScript

// create a script engine manager
ScriptEngineManager factory = new ScriptEngineManager();
// create a JavaScript engine
ScriptEngine engine = factory.getEngineByName("JavaScript");

// expose a, b, c, d
engine.put("a", 1);
engine.put("b", 8);
engine.put("c", 2);
engine.put("d", 3);

// evaluate JavaScript code from String
Number value = (Number) engine.eval("a + b / c * d");
System.out.println(value);

Дополнительные примеры

...