はじめに
よくプログラミング演習や初心者向けスクールなどで、総合演習として「電卓」を作成する課題を与えられることは少なくないと思います。
電卓は簡単そうに見えて初心者には意外と実装の難しいアプリで、市販の電卓に機能が近くなればなるほど難易度が上がります。
どこまで市販電卓との機能を近づけられるか?それをいかに複雑でない構造のコードで実装できるか?が電卓アプリ実装の大きな壁になるとともに、不具合のないすっきりしたコードで実装できれば脱初心者認定しても良い題材であると思います。
本記事はそのような電卓アプリを設計、実装するにあたっての考え方を解説します。もちろん本記事で紹介する方法が唯一無二ではなく、なるべく初心者レベルでも実装と理解がむずかしくなく、かつ特定のプログラミング言語に依存しない考え方を紹介いたします。
前提知識
以下の用語に1つでも聞き覚えがない、理解度が低いモノがあればまだ電卓アプリの実装は時期尚早と考えます。復習しましょう。
- スタック
- 状態遷移
- ifまたはswitchによる場合分け
電卓アプリの基本設計
おそらく一般的な最低限の機能を持った電卓のレイアウトは以下のような画像であると思われます。
- Display: 計算結果や入力過程を表示するディスプレイ
- NumberButton*: 0~9、小数点を入力する数字キー
- OperatorButton: 加減乗除、計算結果を表示する"="キー等、演算子キー
- ClearButton: クリアキー "C" (電卓によっては"AC")
具体的な実装
最初の段階として、"xxx + yyy = "のように毎回"="で計算結果を出すようにするパターンを考えます。
用意する状態変数
- buffer : 入力途中の数字が入る
- stack : 式の左辺と右辺として入力が確定した数値が入る配列
- operator : 入力された演算子が入る
状態遷移図
開始
開始状態は「左辺の数値入力」からとなります。
数字入力の扱い
数字ボタンを押された場合、buffer変数に数字をどんどん追加していきます。
その際、buffer変数の中身が「数値表現として妥当か」を考えなければいけません。
今回の電卓は、数字を入力する分にはどれを入力しても大丈夫ですが、小数点を入力した際は小数点込みの文字列が数値にきちんと変換できるかどうかをチェックしなければなりません。
簡易に実装するのであれば、「小数点が2つ以上存在しない」ことが確認できれば問題ないでしょう。
- 123..
- ..
- 1.2.
などといった表現は数値として適切でないので、こうなる場合は入力された小数点をbufferに追加しないという条件分岐が必要になります。
演算子入力の扱い
プラス、マイナスなどの演算子が押された場合、bufferに入っている文字列をstackに追加します。
stackは配列で、stack[0]
が式の左辺、stack[1]
が式の右辺の扱いとします。
また押された演算子をoperator
変数に入れておきます。最後の計算で使用します。
stackにbufferの内容を移したらbufferは空にして右辺の数値入力の状態になります。
"="が押された場合
右辺にも数値を入力し、"="が押されたらstack
にbuffer
の数値を追加し、計算をする処理に入ります。
operator
変数の中身が何かによって条件分岐を行います。
operator
が"+"だったらstack[0]
とstack[1]
を足し算してdisplayに表示させる、"-"だったらstack[0]
からstack[1]
を引いてdisplayに表示させる、という処理を行います。
計算結果を表示したら、新しい計算をするためにstack
とoperator
,buffer
の中身を空にしておく必要があります。以前の入力状況が残っていたら次の計算に支障が出ます。
発展的な実装
繰り返し演算
通常の電卓は、"1 + 2 + 3 + 5 + ..." というように連続して計算を行うことができます。
上記の処理をどのように改良すればこの機能が実現するか考えてみてください。
2度目の演算子を押されたかどうかは operator
の中に既に演算子が入っているかどうかで判別できます。
その場合は、
- "="が押された時と同じように計算結果を算出する
- 計算結果を
stack[0]
に入れて、stack[1]
は空にする -
operator
変数には、2度目に押された演算子をセットする
という処理を行うことにより、状態遷移図の「右辺キー入力」の状態に戻すことができます。
この状態から続けて数字を入力して計算を行うことができるはずです。