Sachool Engineering Blog

プログラミング学習の記録

電卓アルゴリズム

| Comments

好きなサッカー選手はガットゥーゾです。
こんにちは、東京オフィスのイッセイです。

早速前回の続きを書いていきたいと思います。

今回の課題

問題文

「×」「÷」を加えた電卓アルゴリズムの作成
2+3×4=14
となるようにして下さい。

解決しなければいけない問題がこれでした。

×、÷を優先する処理

モウホントチンプンカンプン。 この時頭の中では、糸がぐるぐる絡まって、ほどけなくなっている状態。固結びが何個も出来ているような。
絡まっている糸を一本ずつほどいていこうと格闘した後が以下の内容です。

まず前回同様
1つの演算子を使いまわす形で解決できるか考える。

うーん、違う。優先できない、、

恐らく10秒はかかってます。
しかし、そこでふと思ったのがこちら。

  • 一回目に+-が入力されたら一度演算子を保留にしておいて、二度目に+-が入力されたら一度目の演算子の左右の数値で演算を行う。
  • 二回目に×÷が入力されたら、もう一度数値を入力して×÷の左右にある数値で演算を行う。
  • ×÷の演算を終えたら変数に代入して加減算として最初に入力された数値と演算を行う。
    以上の繰り返しでどうか。

よしよし、と紙に書いてみるもあっさり失敗。
解決した風に書いてありますけど全然出来てないですね。
連続で×÷が入力された時の処理を考えられていなかったです。
もうそれはそれは驚異的に短絡的な考え方で、、

はい。次!

  • ×÷が入力されたら、+-が入力されるまで同じ処理を繰り返すようにする。
  • 一度目に入力された場合は、+-が入力されるまでその演算結果を変数aに代入する。そして次の数値を変数bに入力し、同じ流れで+-の入力を待つ。
  • 二度目に入力された場合は、一度目に入力されている演算子を記憶しておき、×÷を繰り返した演算結果を変数bに代入する。
  • +-が入力された時、変数aと変数bを記憶していた演算子で演算する。

なんか近づいてきたような。
ところがここで再び致命的なミス。

「=」が入力された場合の処理を考えていない、、

そこで、=が入力された時の事から考える。

=の前に、+-が入力されている場合

  • 変数aと変数bを演算し、変数aに代入し変数aを表示して終了

=の前に、×÷が入力されている場合。

  • 変数aと変数bを演算し、変数aに代入し変数aを表示して終了。(問題はこの先)

更に前に+-が入力されている場合

  • +-の前の変数はaとするため、変数を1つ増やす必要がある。変数cを追加。
  • ×÷の後に変数cに数値を代入して変数bと変数cで演算を行い変数bに代入。これを×÷が出る限り繰り返す。
  • そして、=が入力されたら変数aと変数bを演算して変数aに代入。変数aを表示して終了。
  • 再び+が入力された際は、その前の演算子で変数aと変数bを演算子変数aに代入。

これで繰り返し処理を行う事ができ、×÷の優先にも対応する事ができます!!
後はこの演算子を入力する変数をどうするかを考えるだけです。

最終的に導き出したもの

  • 1度目の演算子入力はop1に。
  • 2度目の演算子入力はop2に。
  • ① op2の演算子入力で+-が入力された場合は、
    変数aと変数bをop1で演算し変数aに代入。op2をop1に代入し、その後op2に演算子を入力する。
  • ② op2の演算子入力で×÷が入力された場合は、
    変数bと変数cをop2で演算し変数bに代入。その後op2に演算子を入力する。
  • =が入力された場合、変数aと変数bをop1で演算して変数aに代入し、変数aを表示して終了。
  • op2に演算子を入力した後、①、②のどちらかのパターンを繰り返す。

実装して検証する。

上記で考えたものを実装していきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
 #include <cstring>
 #include <cctype>
 #include <iostream>
 using namespace std;
 int main(){
    double a,b,answer;
    char op1,op2;
    cout <<"演算開始\n加算:+ 減算:- 乗算:* 除算:/ 終了:=\n";
    
    for ( cin >> a ; !cin ; cin >> a){
        cin.clear();
        cin.ignore();
        cout <<"数値を入力して下さい";
    }
    
    answer = a;
    for ( cin >> op1; !(op1 == '+'||op1 == '-'||op1 == '*'||op1 == '/'||op1 == '='); cin >> op1){
        cin.clear();
        cin.ignore();
        cout <<"演算子をを入力して下さい";
    }
   
    if(op1 == '=') goto Ending;
    
    
    for ( cin >> b ; !cin ; cin >> b){
        cin.clear();
        cin.ignore();
        cout <<"数値を入力して下さい";
    }
    
    for ( cin >> op2; !(op2 == '+'||op2 == '-'||op2 == '*'||op2 == '/'||op2 == '='); cin >> op2){
        cin.clear();
        cin.ignore();
        cout <<"演算子をを入力して下さい";
    }
    
    
    do{
        if(op2 == '+' || op2 == '-'){
            switch(op1){
                case '+' : a = a + b; break;
                case '-' : a = a - b; break;
                case '*' : a = a * b; break;
                case '/' : a = a / b; break;
            }
            op1 = op2;
            
            for ( cin >> b ; !cin ; cin >> b){
                cin.clear();
                cin.ignore();
                cout <<"数値を入力して下さい";
            }
        }else if(op2 =='*' || op2 == '/'){
            double c;
           
            for ( cin >> c ; !cin ; cin >> c){
                cin.clear();
                cin.ignore();
                cout <<"数値を入力して下さい";
            }
            switch(op2){
                case '*' : b = b * c; break;
                case '/' : b = b / c; break;
            }
        }else break;
        for ( cin >> op2; !(op2 == '+'||op2 == '-'||op2 == '*'||op2 == '/'||op2 == '='); cin >> op2){
            cin.clear();
            cin.ignore();
            cout <<"演算子をを入力して下さい";
        }
    }while(op2 != '=');
    
    switch(op1){
        case '+' : answer = a + b; break;
        case '-' : answer = a - b; break;
        case '*' : answer = a * b; break;
        case '/' : answer = a / b; break;
    }
    Ending :
    cout << answer <<"\nfin";
 }

多々修正を行いました。
実装してみて、ループの戻り先がハチャメチャだった事に気付いたからです。
do-while文の部分は、実際作成したフローチャートではとても実装できるような処理の流れではありませんでした。
しかし、コードのことを考えながらアルゴリズムを考える事ができればもう少し考えやすくなるかも、と思いました。以後試したいと思います。

まとめ

以上で今回の課題は終了ですが、中々苦戦したこの課題を通して大事な事を学びました。
私はこれまで無意識に、短絡的な考えのもと生活をしてきた事に気付きました。
そしてそれがアルゴリズムを考えるだけでなくエンジニアとして生きていくうえで致命的であることを身をもって感じました。
求める結果から課題を導き、順序だてて解決していかなければならない。
都度、論理的に考えられているか自分で確認しながら取り組んでいこうと思います。
大事というか、今更かよ!的な話ですが、、
こんな私の成長を、ブログから感じ取っていただけるよう今後も精進いたします。

Comments