2016-10-07 6 views
0

私はAndroidのプログラミング(Androidスタジオを使用して)を教えて、私は基本的な電卓のアプリに取り組んでいます。私のevalメソッドはDijkstraのshunting-yardアルゴリズムを使用して文字列式を解析し、その結果を計算します。私はthis SO questionからこれのアイデアを得ました。次のようにJava - Stack.popに最後の項目が返されない

私の評価者クラスのコードは次のとおりです。

class Evaluator { 
    private static Evaluator instance = new Evaluator(); 

    private Stack<String> mOperators; 
    private Stack<Double> mOperands; 

    public static Evaluator getInstance() { 
     return instance; 
    } 

    private Evaluator() { 
     mOperands = new Stack<Double>(); 
     mOperators = new Stack<String>(); 
    } 

    public Double eval(String expression) { 
     Stack stack = convertExpressionToStack(expression); 
     buildOperationStacks(stack); 
     return doEval(); 
    } 

    private Double doEval() { 
     while (!mOperators.isEmpty()) { 
      String op = mOperators.pop(); 
      Double v = mOperands.pop(); 

      switch (op) { 
       case "+": 
        v = mOperands.pop() + v; 
        break; 
       case "-": 
        v = mOperands.pop() - v; 
        break; 
       case "*": 
        v = mOperands.pop() * v; 
        break; 
       case "/": 
        v = mOperands.pop()/v; 
        break; 
      } 

      mOperands.push(v); 
     } 

     return mOperands.pop(); 
    } 

    private void buildOperationStacks(Stack stack) { 
     while (!stack.isEmpty()) { 
      String s = (String) stack.pop(); 

      switch (s) { 
       case "+": 
       case "-": 
       case "*": 
       case "x": 
       case "X": 
       case "/": 
       case "÷": 
        if (s.equals("x") || s.equals("X")) { 
         s = "*"; 
        } else if (s.equals("÷")) { 
         s = "/"; 
        } 

        mOperators.push(s); 
        break; 
       default: 
        try { 
         if (!stack.isEmpty() && stack.peek().equals (".")) { 
          s += stack.pop(); 
          s += stack.pop(); 
         } 

         mOperands.push(Double.parseDouble(s)); 
        } catch (Exception e) { 
         Log.e("Error", e.getMessage()); 
        } 
      } 
     } 
    } 

    private Stack convertExpressionToStack(String expression) { 
     Stack<String> s = new Stack<String>(); 

     for (char c : expression.toCharArray()) { 
      s.push(String.valueOf(c)); 
     } 

     return s; 
    } 
} 

だから私の問題は、doEval方法です。各スタックから要素をポップすると、各スタックに最初の要素が追加されています。私はスタックがFirst In Last Out構造であったという印象を受けました。

どうしたらいいですか?どうやら各スタックを逆転させる必要がありますか?

ありがとうございます。

EDIT

ですから、例えば、I入力5 + 3 * 2。私はこれをデバッグするとき、私は見ています、実行はしかし

pass 1: value1 = 2, Operator1 = *, value2 = 3 result = 6 
pass 2: Value1 = 6 (result of pass 1) Operator1 = +, value2 = 5 result = 11 

ことを期待する:スタックの

pass 1: value1 = 5, Operator1 = +, value2 = 3, result = 8 
pass 2: value1 = 8 (result of pass 1), operator1 = *, value2 = 2, result = 16 
+0

スタックはLIFOで、http://docs.oracle.com/javase/を参照してください8/docs/api/java/util/Stack.html –

+0

@RC。 - 仰るとおりです。 First Out Last OutはLast In First Outと同じです。しかし、私のスタックはFirst In First Outとして機能しています。私は彼らがなぜこのように行動しているのか理解していません –

+0

LIFOはFILOと同じではありませんか?しかし、あなたがライフやフィロを使っているかどうかは関係ありません。しかし、それは同じではありません –

答えて

3

convertExpressionToStack()メソッドは、正しい順序でオペランドスタックを構築していますが、buildOperstionStack()メソッドは、1つをポップしてもう一方を押して反転しています。

あなたは本当にとにかく、この第二の方法は必要ありません。ただ乗算などxを理解するための評価方法を変更する、など

+0

私は理解します。情報をありがとう。私は今これを実装します。 –

0

あなたの理解は正しいです。それは最初の、最後の最後の、最後の、最初のものです。あなたのコードについて

while (!mOperators.isEmpty()) { 
      String op = mOperators.pop(); 
      Double v = mOperands.pop(); 

      switch (op) { 
       case "+": 
        v = mOperands.pop() + v; 
        break; 
       case "-": 
        v = mOperands.pop() - v; 
        break; 
       case "*": 
        v = mOperands.pop() * v; 
        break; 
       case "/": 
        v = mOperands.pop()/v; 
        break; 
      } 

      mOperands.push(v); 
     } 

以来、あなたはそれがどのように動作しているかを正確に、言及した、そう、私が説明させていません。 +

mOperands has 3,6,2,1 

の上にこれはあなたのコードがして振る舞うべきでしょうかである - +は、第1および追加された場所 - mOperatorsは、+持っている、と仮定します。 vは今1であるから、あなたのmOperandsはなり

op = - 
v = 1 
v = 2-1 = 1 // since it's a - 

mOperands is now: 3,6 

とコールした後、mOperands.push(V)、::

3,6,1 whileループの最初の繰り返しのために

whileループの

2回目の反復:

op = + 
v = 1 
v = 6+1 = 7 // since op is + 

あなたmOperandsは今、次のようになります。3

そして、それはスイッチから壊れたら、それはようmOperandsを行います:

3,7

PS:あなたはより良いアイデアを得るためにそれぞれすべての段階でmOperandsの値を参照するようにアプリケーションをデバッグする必要があり、なぜそれがそうであるかのように行動している。

+1

ありがとうございます。私は私のアプリをデバッグしていて、例を示すために質問を編集します。 –

関連する問題