92032
一行電卓のプログラムを作成しています。"1+1"など2つの数字を使用した場合の計算は成功するのですが、数字が3つ以上（例①10+10+10、②1+1+1+1+1+1)の場合、正しく計算されません。例①の答えは10、例②の答えは3になってしまいます。下記にコードを記載ましたので、アドバイスいただけると幸いです!

———-以下コード—————

```

    package Calclator;
    
    import java.util.Scanner;
    
    public class Main {
    
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            System.out.println("input numbers and operator");
            System.out.println("operator: +, -, x, ÷,%,^,r(square root)");
            System.out.println("symbol: =");
            
            while (true) {
                String[] user_input = new String[4];
                for (int i = 0; i < user_input.length; i++) {
                    user_input[i] = new java.util.Scanner(System.in).nextLine();
                }
                if (user_input[0].equals("")) { 
                    System.out.println("Over");
                    break;
                } else if (user_input[1].equals("")) { 
                    System.err.println("Error");
                    continue;
                }
            
                String[] ops = { "+", "-", "×", "÷", "%", "^", "r" };
    
                if (!(user_input[1].equals(ops[6])) && user_input[3].equals("")) {
                    int calc;
                    int digit1 = Integer.parseInt(user_input[0]);
                    int digit2 = Integer.parseInt(user_input[2]);
                    int ans = calc(digit1, digit2, user_input);
                    System.out.println(ans);
                } else if (user_input[1].equals(ops[6]) && user_input[3].equals("")) {
                    double calc2;
                    double digit3 = Double.parseDouble(user_input[0]);
                    double result = calc2(digit3, user_input);
                    System.out.println(result);
                } 
                    
                else if (!(user_input[3].equals(""))) {
                    user_input = tempArray(user_input);
                }
    
                for (int i = 0; i < user_input.length; i++) {
                    user_input[i] = new java.util.Scanner(System.in).nextLine();
                }
                int calc;
                int digit1 = Integer.parseInt(user_input[0]);
                int digit2 = Integer.parseInt(user_input[2]);
                int digit4 = Integer.parseInt(user_input[4]);
    
                int interAns = calc(digit1, digit2, user_input);
                int newAns = calc4(digit4, interAns, user_input);
                System.out.println(newAns);
            }
        }
    
        public static int calc(int digit1, int digit2, String[] user_input) {
            if (user_input[1].equals("+")) {
                return digit1 + digit2;
            }
            if (user_input[1].equals("-")) {
                return digit1 - digit2;
            }
            if (user_input[1].equals("×")) {
                return digit1 * digit2;
            }
            if (user_input[1].equals("÷")) {
                return digit1 / digit2;
            }
    
            if (user_input[1].equals("%")) {
                return digit1 % digit2;
            }
            if (user_input[1].equals("^")) {
                return digit1 ^ digit2;
            }
            return 0;
        }
    
        public static double calc2(double digit3, String[] user_input) {
            if (user_input[1].equals("r")) {
                double A = Math.sqrt(digit3);
                return A;
            }
            return 0.0;
        }
    
        public static String[] tempArray(String[] user_input) {
            String[] temp_input = new String[user_input.length + 3];
            for (int i = 0; i < user_input.length; i++) {
                temp_input[i] = user_input[i];
            }
            user_input = temp_input;
            return user_input;
        }
    
        public static int calc4(int digit4, int interAns, String[] user_input) {
            if (user_input[3].equals("+")) {
                return interAns + digit4;
            }
            if (user_input[3].equals("-")) {
                return interAns - digit4;
            }
            if (user_input[3].equals("×")) {
                return interAns * digit4;
            }
            if (user_input[1].equals("÷")) {
                return interAns / digit4;
            }
            if (user_input[3].equals("%")) {
                return interAns % digit4;
            }
            if (user_input[3].equals("^")) {
                return interAns ^ digit4;
            }
            return 0;
        }
    }
    
```
CC BY-SA 4.0
2022-11-05T22:17:18.817
92022
2022-11-06T12:16:48.533
2022-11-06T00:03:07.630
19110
55185
question
java
式を計算する電卓を作ったところ、式に複数の演算子があるとうまく計算されない
ロジックとしては長さ４の配列を用意して  
とりあえず４つ読んで  
num op num をこえたら（４つめが空文字列じゃなければ）

配列の長さを＋３延長して長さ７にして  
num op num op num op num  
までうけとれるようにしたってことでいいんですよね

ただその後の

```

                for (int i = 0; i < user_input.length; i++) {
                    user_input[i] = new java.util.Scanner(System.in).nextLine();
                }
    
```

の追加入力を受け取る部分で  
もう１度配列の先頭からいれちゃってるので  
最初に受け取った値を上書きしちゃってるのがまずいかも

```

                System.out.println("===== ここまでの入力 =====");
                for(int i = 0; i < user_input.length; i++)
                    System.out.print(user_input[i]);
                System.out.println();
                System.out.println("==========================");
    
```

こんな感じのデバッグを入れてみるとわかりやすいかも

実行結果

```

    java Main
    input numbers and operator
    operator: +, -, x, ÷,%,^,r(square root)
    symbol: =
    1
    +
    2
    +
    3
    +
    4
    +
    5
    +
    6
    ==== ここまでの入力 ====
    3+4+5+6
    ========================
    
```

とおそらく追加で３つだけ受け取るはずが  
合計１１回入力を要求されて  
最初の 1 + 2 がなかったことになってます

なのでこの部分を０からじゃなく４番目以降にうめるようにすれば入力はうまくいくかと

```

                for (int i = 4; i < user_input.length; i++) {
                    user_input[i] = new java.util.Scanner(System.in).nextLine();
                }
    
                System.out.println("===== ここまでの入力 =====");
                for(int i = 0; i < user_input.length; i++)
                    System.out.print(user_input[i]);
                System.out.println();
                System.out.println("==========================");
    
```

実行結果

```

    > java Main
    input numbers and operator
    operator: +, -, x, ÷,%,^,r(square root)
    symbol: =
    1
    +
    2
    +
    3
    +
    4
    ===== ここまでの入力 =====
    1+2+3+4
    ======================
    6
    
```

10 にならずに 6 にしかならないのは

```

                int digit1 = Integer.parseInt(user_input[0]);
                int digit2 = Integer.parseInt(user_input[2]);
                int digit4 = Integer.parseInt(user_input[4]);
    
                int interAns = calc(digit1, digit2, user_input);
                int newAns = calc4(digit4, interAns, user_input);
    
```

でいま 2 4 6 番目までの計算しかやってないからです

* * *

そもそも 1 + 2 * 3 みたいな入力が合っても 1 + (2 * 3) のように  
後に入力したものを先に計算したいみたいな要件はなく  
常に左側結合で (1 + 2) * 3 を計算すればいいってことですよね？

つまり 1 + 2 の時点で 3 を計算してしまって  
* 3 を受け取る時点で 1 + 2 の結果だけ持ってれば入力は捨ててしまっていいわけです

なら配列を使わなくても op + digit を読んだ時点で現在の数字を更新していけばよくって  
/num (op num)* "r"?/ の正規表現を受理するスタックマシンでいいんですよね  
昔の計算機がそういう方式を採用してたので興味があれば「スタックマシン」とかでぐぐって調べてみてください

こんな感じで比較的シンプルに書けるしメモリにも優しいです

```

    import java.util.Scanner;
    
    public class Main {
    
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            System.out.println("input numbers and operator");
            System.out.println("operator: +, -, x, ÷,%,^,r(square root)");
            System.out.println("symbol: =");
            
            while(true) {
    
                // 最初は数字確定
                int interAns = Integer.parseInt(new java.util.Scanner(System.in).nextLine());
    
                // 以降は op (+ num) を読んで現在の数字を更新していく
                while (true) {
                    // 次は OP 確定
                    String op = new java.util.Scanner(System.in).nextLine();
    
                    // op が空 = 入力終了 => 現在の結果表示して最初の入力まで戻る
                    if(op.equals("")) {
                        System.out.println(interAns);
                        break;
                    }
    
                    // ルートの場合だけ次の数字を要求しない
                    if(op.equals("r")) {
                        System.out.println(calc2(interAns, op));
                        // 計算結果が double になってしまうのでここでおわりでいいのかな？
                        break;
                    }
                    // ルート以外は次の数字を読んで途中結果を更新
                    else {
                        int digit = Integer.parseInt(new java.util.Scanner(System.in).nextLine());
                        interAns = calc4(digit, interAns, op);
                    }
    
                    // デバッグ用
                    System.out.println("interAns = " + interAns);
                     
                    // また次の op を読むためにループ
                }
    
            }
        }
    
    
        public static double calc2(double digit3, String op) {
            if (op.equals("r")) {
                double A = Math.sqrt(digit3);
                return A;
            }
            return 0.0;
        }
    
    
        public static int calc4(int digit4, int interAns, String op) {
            if (op.equals("+")) {
                return interAns + digit4;
            }
            if (op.equals("-")) {
                return interAns - digit4;
            }
            if (op.equals("×")) {
                return interAns * digit4;
            }
            if (op.equals("÷")) {
                return interAns / digit4;
            }
            if (op.equals("%")) {
                return interAns % digit4;
            }
            if (op.equals("^")) {
                return interAns ^ digit4;
            }
            return 0;
        }
    }
    
```

実行結果

```

    > java Main
    input numbers and operator
    operator: +, -, x, ÷,%,^,r(square root)
    symbol: =
    1
    +
    2
    interAns = 3
    +
    3
    interAns = 6
    +
    4
    interAns = 10
    
    10
    
```
CC BY-SA 4.0
2022-11-06T07:40:23.233
92032
2022-11-06T07:40:23.233
92022
answer