0

私はJavaを学んでいる途中で、最初のプロジェクトは電卓ですが、問題が発生しました。電卓で数値を入力してから演算子(+、-、x、/)をクリックし、別の数値を入力してからもう一度演算子を押すと、表示が更新され、これを続行できるようになります。

たとえば、次をヒットして、最初の後にオペレーターをヒットするたびに合計を表示できるようにしたいと思います。

a + b / c --d =

私が持っているコードは(私には)機能するはずのように見えますが、機能しません。私は何が間違っているのですか?

以下は、オペレーターをヒットしたときに使用しているコードです。デフォルトでは、待機はfalseに設定されています。クラスを1回実行した後、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

いくつかの提案。

まず、ステートメントbooleanの条件としてaを使用する場合は、とのif比較を避けてください。とにかく、状態は2つだけです。また、状態は2つしかないため、を使用するのではなく、次のようになります。truefalsebooleanelse 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変数)またはenumsを使用してみてください。が同じであるかどうかではなく、文字列リテラルと変数の両方同じオブジェクトを参照しているかどうかを確認するためのチェックを実行するStringなどの比較を行います。したがって、特定の状況下では、に設定されている場合がありますが、文字列リテラルが別のオブジェクトを参照しているため、比較が行われない場合があります。簡単な回避策は次のとおりです。(operator == "add")"add"operatoroperator"add"true

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

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

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

現在、両方の割り当てoperatorと比較のoperator両方が定数operatorAddを参照しているため、比較==ではメソッドではなくを使用できますequals()

第三に、これは実際には2つのオペランド(つまり)を必要とせず、格納された値(つまり)に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;
}

上記のコードは単一のループを使用し、イベントベースのGUIモデルのようには機能しませんが、電卓を実行するために必要な手順の概要を示す必要があります。

于 2009-01-24T06:23:48.610 に答える
3

演算子を入力するたびに、コードはこれを実行します。

Double.valueOf(s.trim())

value1またはvalue2(に応じて)のいずれかを設定しますwait。演算子はdoubleとして解析できないため、これは例外をスローします。入力を数値として解析する前に、最初に演算子をチェックする方が幸運かもしれません。その後、演算子の場合は、数値解析の部分をスキップできます。

また、誰かが2つの数字または2つの演算子を続けて入力した場合にどうなるかを検討してください。

于 2009-01-24T05:57:25.120 に答える
1

グレッグが言ったように、入力が何であれ、現在のプログラムの状態が何であれ、あなたは常に数を解析します。プログラムの状態をより明確に追跡する必要があります。あなたがコーディングするとき、「String s = output.getText();」があると思います。つまり、実際には「String s = input.getText();」という意味です。

また、注意してください

  if(wait == false){
    //!waitのスタッフ
  } else if(wait == true){
    //待つもの
  }

不必要に冗長です。次のように置き換えることができます。

  if(!wait){
    //!waitのスタッフ
  } そうしないと {
    //待つもの
  }

おそらく、最初に入力文字列をチェックして、それが演算子であるかどうかを確認し、そうでない場合は、数値であることを確認する必要があります。(優先順位を適切に処理する)中置計算機を作成することは簡単ではありません。

于 2009-01-24T06:10:01.787 に答える
0

高低を検索した後、問題は私が提供したコードにあるのではないと最終的に判断しました。「wait = false;」がありました。実行を台無しにしていた私の 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 に答える