0

我正在学习 Java,我的第一个项目是计算器,但是我遇到了障碍。我试图让我的计算器让我输入一个数字,然后单击一个运算符(+、-、x、/),输入另一个数字,然后再次点击一个运算符并让显示更新并能够继续进行。

例如,我希望能够点击以下内容,并在每次点击操作员后显示总数:

a + b / c - d =

我拥有的代码(对我而言)似乎应该可以工作,但事实并非如此。我究竟做错了什么?

以下是我在点击运算符时使用的代码。默认情况下,等待设置为 false。运行完该类一次后, value1 被存储并将 wait 设置为 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 语句。即使在此之后,同样的问题仍然存在。此外,完整的源代码可在此处获得

4

5 回答 5

4

几点建议。

首先,我建议在使用 aboolean作为if语句的条件时,避免与trueand进行比较——反正false只有两种状态。boolean此外,由于只有两种状态,而不是 using else if (false), anelse就足够了:

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变量)或enums。进行String比较,例如(operator == "add")检查字符串文字"add"operator变量是否都引用同一个对象,而不是是否相同。因此,在某些情况下,您可能operator设置为,"add"但比较可能不是true因为字符串文字引用了一个单独的对象。一个简单的解决方法是:

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

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

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

现在,两者的赋值operator和比较operator都引用了常量operatorAdd,所以比较可以使用 a==而不是equals()方法。

第三,由于这似乎是不需要两个操作数(即)的计算器类型,operand1 + operand2而是一个作用于存储值的单个操作数(即operand + currentValue当前值,另一个保存运算符的变量,以及一个根据当前运算符和操作数进行操作的方法。(或多或少是累加器或单操作数计算机的概念。)

基本的操作方法是:

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

尽管上面的代码使用单个循环并且不像基于事件的 GUI 模型那样工作,但它应该概述了运行计算器所需的步骤。

于 2009-01-24T06:23:48.610 回答
3

每当您输入运算符时,您的代码都会执行以下操作:

Double.valueOf(s.trim())

用于设置value1value2(取决于wait)。这将引发异常,因为运算符不能被解析为双精度。在尝试将输入解析为数字之前,您可能会更幸运地检查运算符。那么如果是算子,就可以跳过数字解析部分。

还要考虑如果有人连续输入两个数字或两个运算符会发生什么。

于 2009-01-24T05:57:25.120 回答
1

正如格雷格所说,无论输入是什么,无论当前程序状态如何,您总是会解析出数字。您需要更清晰地跟踪程序状态。我假设当你的代码有“String s = output.getText();” 你的意思是“String s = input.getText();”。

另请注意

  如果(等待==假){
    // !wait 的东西
  } else if (wait == true) {
    // 等待的东西
  }

是不必要的冗余。您可以将其替换为:

  如果(!等待){
    // !wait 的东西
  } 别的 {
    // 等待的东西
  }

您可能应该首先检查输入字符串以查看它是否是运算符,如果不是,则确保它是数字。编写一个中计算器(正确处理优先级)并非易事。

于 2009-01-24T06:10:01.787 回答
0

经过高低搜索后,我终于确定问题不在我提供的代码中。我有一个“等待=假;” 在我的 NumberListener 类中搞砸了执行。为了解决这个问题,我创建了 2 个单独的等待变量,到目前为止一切正常。

感谢您的帮助和提示,+1 对你们所有人的尝试。

于 2009-01-25T02:42:22.597 回答
-1

您可以使用 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);

更多示例

于 2009-01-24T07:29:44.187 回答