※アクセス解析を見ると、電卓を作るシリーズがよく閲覧されているようなので、気が付いたことは随時追記していこうかなと思っております。こんな初心者が書いた記事を閲覧していただき誠に感謝です。
詳しく解説するために文章がかなり多めになってしまっていますが、上から順に読めばわかるようにしているつもりです。こちらも都度ブラッシュアップしていくつもりです。
こんばんは。まるです。
C#で電卓を作るシリーズですが、私が困ってネットで調べると専門用語がむずかしかったり、なんでこんなに難しい表現でないと伝えられないのかなという記事が多い印象です。
そこで電卓をトータル5日で完成させた私が、やりたてほやほやかつ初心者である今にわかりやすく記事をまとめることによってほかの私と同じく初心者プログラマーの助けになれればなと思って書いてます。
さて本題です。
なぜ”1+2+3=”の処理が難しいのかですが、
前回の記事で書きましたが、+を押した瞬間firstNumに、表示されている文字が格納されると書きました。
つまり、1+ の時点で1がfirstNumに格納されてます。
次に2が押されて、そのあと+が再び押されると。。。
そうです、firstNumの数字が2に書き換えられてしまい、3を押してつぎに=を押すと答えが5になってしまうんです!
これには困りました。
最初はfirtNumを2つ用意して、2つとも格納しておいてあとで引っ張り出せばいいと考えたのですが、
これには大問題があって、1+1+1+1+1+1。。。となっていくたびにfirstNumを増やしていかなければいけない問題が生じるのです!!
さあ困りました。どうしよう。
あれこれいろいろ思考したのですが、結論としては、1+2+の時に、もう1+2を済ませて3をディスプレイに表示させればいいんだと理解しました。
(2020年10月6日追記:配列やListでもよい。仕事が落ち着いたら配列で作った電卓についても記事にする予定。)
実際いろいろな電卓でこの処理が使われていたりします。
そして足してやったものをfirstNumに入れる、とすればfirstNumは一つですみます。
ただし、最初の+と2回目の+が違うものですよというのを理解させてあげないといけません。
これも非常に悩みました。最初の+を押したときに、+が押されたよ!とするためにつかったのがopeFlgです。
opeFlgがtrue(on)の時、数字を押すとディスプレイの文字を+の次に押した数字に変える、という処理をしていましたよね。
なので2回目の+を押したときに、1+2の結果を表示させないといけないのに、一回目と同じ処理をしてしまうと2が表示されてしまいます。
残念ながら1回目の処理とか2回目の処理といったコマンドはなく(あるのかもしれないけど今の私は知らない)、どうにか1回目と2回目(細かく言うと2回目以降は足されていくので同じものでよい)の+押下処理を変える方法はないか。
これはまるまる1日くらい悩みました。なぜならほかにも気になることがあって、やる必要なかったマイナス計算の実装を同時にやってしまっていてごちゃごちゃになってしまったからです。
話を戻して結論を言いますと、
1回目はopeFlgを、2回目はopeFlg2を用意してこれのON,OFFを使うことで解決しました。
どういうことかというと、一回目にopeFlgとopeFlg2をtrueにします。
(opeFlg = true opeFlg2 = true の状態)
そして一回目のプラスのあとの数字(今回は2)が押されたときに、opeFlgだけをオフにします。
(opeFlg = false opeFlg2 = true の状態)
そして次のプラスが押されたときに、条件分岐をさせまして、opeFlgがfalse(off状態)で、opeFlg2がtrueなら、ディスプレイの数字とfirstNumに格納された数字(この場合1)を足してテキストディスプレイに表示するとしました!
( if (opeFlg == false 且つ(&&) opeFlg2 = true の状態で+が押下された場合 )
(txtDisplay.Text += firstNum
※「=」をはさんだ左右のオペランド(式)は型が一致している必要があります。
なので型変換を行う必要ありです .ToString() )
これで万事解決です。あとは足した数字がディスプレイに表示された後にopeFlgとopeFlg2をオンオフしてあげればいいのです。
(ふと思ったけどfirstNumの数字を裏で足したり引いたりすればいいんじゃないのって今思いはじめた。後でやってみよう)
これで1+2+3=6が完成しました。
細分化して日本語で説明すると、
(基本的に文字を読みながら図をみる形で、図だけ見ると目が回ります)
図にした方がわかりやすいかなとおもったんですがそうでもなかったですね。
なのでコードを交えて再度解説します。
【・1が押下される 時】
・ ディスプレイに1を表示する。
txtDisplay.Text = "1";
※ボタンのTextを1にして、txtDisplay.Text = btn1.Text; のようにした方がよいかなと思います。理由は、「1」と書いたつもりが「1」だった。なんていうことが起きるからです。最初の1は半角、後者の1は全角です。なるべく定数を使ってあげた方が間違いがなく良いかなと思います。もちろん動作的には両方同じです。
【・+が押下される 時 ※「1+」の時】
・ラベルに「+を表示する」
lblBox.Text = "+" ;
・演算子が押された状態であることを後に条件にするために、スイッチを切り替える(便宜上の例え)
opeFlg = true ;
opeFlg2 = true ;
・最初に押された数字を格納する箱(firstNum)に+が押された時のディスプレイの数字を格納する
firstNum = int.Parse ( txtDisplay.Text ) ;
※lblBox.Text = "+" ; ←これも上に同じでbtnPuls.Textを使う方がよいでしょう。
※型を一致させるためにstring→intを行う必要あり、
「int.Parse(intにしたいstring型のなにか) 」を行う。あるいはそもそもfirstNumをstringで用意するか。
【・ 2が押下される 時 ※「1+2」の時】
・条件:もしopeFlgがtrueである時、
( if (opeFlg == true ) または if (opeFlg) ←これでも暗黙的にtrueであること、となります)
txtDisplay.Text = "2"; ※しつこく繰り返しますが、btn2.Textがよいと思います。
・その後、数字が押されたのでopeFlgを切り替える。
※これを行わないと、連続して数字が押された時に、都度押された数字だけが表示されてしまう
opeFlg = false ; ※これによりopeFlg = false opeFlg2 = true の状態
【・再び+が押下される 時 ※「1+2+」の時】
・連続して演算子が押された場合の条件式
if ( opeFlg == false && opeFlg2 == true )
・ディスプレイに1と2を計算したものを表示させる
txtDisplay.Text = (int.Parse(txtDisplay.Text) + firstNum).ToString();
※ここが非常にめんどくさいのですが、まず計算をするためにstring型であるディスプレイの「文字(1)」を「数字」に直します。計算した後は「=」をはさんだ左右のオペランド(式)は型が一致してないといけないルールに従い、「数字→文字」を行います(.ToString)
【・3が押下される 時 ※「1+2+3」の時】
・ディスプレイに3を表示する
※この時点で既に3(1+2の)が表示されているのでやや紛らわしい。
txtDisplay.Text = "3"; ※繰り返しますがボタンのTe .................................(ry)
・数字が押されたのでopeFlgはオフにする
opeFlg = false;
【・=が押下される 時 ※「1+2+3=」の時】
・ディスプレイにfirstNumに格納した数字(1+2の3)と現在表示されている3を足したもの(6)を表示する。
txtDisplay.Text = ( firstNum + int.Parse(txtDisplay.Text) ).ToString()
・初期化する。
firstNum = 0 ;
opeFlg = false ;
opeFlg2 = false ;
こんな感じです。伝わりましたかね?
どこの記事よりも砕いて説明したつもりですが、もしこれでわからない場合は
コメントください。その時はコード載せます(その時までにもっと簡略化しておきます汗)
↑簡略化するつもりがより文章多めになってしまいました汗
今回は以上です。お待たせする形になってすみませんでした。
それではまた。