この章では、数字ボタンが押されたときの処理を見てみましょう
前提条件
各数字ボタンが押される直前の電卓はどのような状態の場合があるかを考えてみます
| 演算子の表示部分 | 数値の表示部分 | 変数 | 状態の説明 |
|---|---|---|---|
| 空 | 空 | current_buffer:空 last_operator:空 stack[0]:空 stack[1]:空 | 電卓の起動時 |
| 空 | 数値 | current_buffer:数値 last_operator:空 stack[0]:空 stack[1]:空 | 電卓起動後数値または小数点を入力 |
| -、+、×、÷ | 数値 | current_buffer:空 last_operator:演算子 stack[0]:左辺値の値または計算結果 stack[1]:空 | 演算子を指定した状態 |
| = | 数値 | current_buffer:空 last_operator:= stack[0]:計算結果 stack[1]:空 | 計算完了後の状態 |
処理内容
ディスプレイに押された数字ボタンを末尾に追加し、current_bufferに押された数字ボタンを追加する処理を実行します
数値ボタンのイベント処理フロー
1. 状態のチェック
もしlast_operatorが’=’または演算子の場合、これは「新しい計算」が始まることを意味します
2. 処理内容
-
「新しい計算」の状態の場合
- last_operator が”=”のとき
・ UIの数値表示部分をクリアする
・ UIの演算子表示部分をクリアする
・ すべての変数をクリアする - llast_operatorが”=”以外の演算子のとき
・ UIの数値表示部分をクリアする
- last_operator が”=”のとき
- 入力された数字をcurrent_bufferに追加する(特殊なケースを考慮しながら)
- UIの数値表示部分を、更新されたcurrent_bufferの値で上書きする
数値の表示部分の数値が選択した数値に代わります
特殊なケース
特殊なケースは以下の2点を想定します
- 0の入力後、別の数字が押された場合
01とは表示されないようにcurrent_bufferの先頭が0かつ小数点が存在しない場合、先頭の0を入力した数値に置き換えます
0.と小数点が存在する場合は、末尾に選択した数値を追加します - 入力桁数が上限に達した場合
整数部と小数部の合計が、上限値以上の値は受け付けないようにします
実装
イベントハンドラの設定
VisualC++の機能を使用して0~9までのボタンのイベントハンドラを作成します
各ボタンをダブルクリックし、作成された関数は次の通りです
- MyCalculatorDlg.h
afx_msg void OnBnClickedButtonZero();
afx_msg void OnBnClickedButtonOne();
afx_msg void OnBnClickedButtonTwo();
afx_msg void OnBnClickedButtonThree();
afx_msg void OnBnClickedButtonFour();
afx_msg void OnBnClickedButtonFive();
afx_msg void OnBnClickedButtonSix();
afx_msg void OnBnClickedButtonSeven();
afx_msg void OnBnClickedButtonEight();
afx_msg void OnBnClickedButtonNine();
各数字ボタンの処理は、MyCalculatorDlg.cppのそれぞれのイベントハンドラへ記述していきます
数字ボタンのソース
数値ボタンの動作について、実装したソースは次の通りです
各数値ボタンでの処理は、入力する文字以外はすべて共通になるため、各数値ボタンのイベントハンドラから、数値共通の関数HandleNumberClick(LPCTSTR number_char)を呼び出すようにしています
また、数値を文字列に変換するConvertDoubleToCString(double result)関数を追加します
/* double型の引数をCString型に変換する */
/* 不要な0は削除して表示する */
/* (例)15.00000→15 */
CString CMyCalculatorDlg::ConvertDoubleToCString(double result) {
CString buffer;
// 精度を大きく指定して指数表記を抑制する
// 例: 15桁の有効数字
buffer.Format(_T("%.15g"), result);
return buffer;
}
// 数字ボタンの共通処理を行う関数
void CMyCalculatorDlg::HandleNumberClick(LPCTSTR number_char)
{
// 「新しい計算」の状態の場合の処理
if(last_operator == _T("="))
{// 最後に入力した演算子が=の場合
OnBnClickedButtonAc();
}
else if (current_buffer.IsEmpty())
{ // =以外の演算子のあと
setEditBoxText(_T(""));
}
// current_bufferの桁数をチェックする
// 10桁以上の場合は入力をさせないように対応する
if (current_buffer.GetLength() >= 10) {
return;
}
// 入力できる状態ならば、指定された値を追加する
current_buffer += number_char;
size_t pos = current_buffer.Find('.');
if (pos == -1) { // 小数点以下の入力ではないとき
// 先頭が0のとき0を削除するため(01の場合0にする)
double result = _tcstod(current_buffer, NULL);
current_buffer = ConvertDoubleToCString(result);
}
// 入力中の文字列をコントロールに出力する
setEditBoxText(current_buffer);
}
void CMyCalculatorDlg::OnBnClickedButtonZero()
{
// TODO: ここにコントロール通知ハンドラー コードを追加します。
HandleNumberClick(_T("0"));
}
void CMyCalculatorDlg::OnBnClickedButtonOne()
{
// TODO: ここにコントロール通知ハンドラー コードを追加します。
HandleNumberClick(_T("1"));
}
void CMyCalculatorDlg::OnBnClickedButtonTwo()
{
// TODO: ここにコントロール通知ハンドラー コードを追加します。
HandleNumberClick(_T("2"));
}
void CMyCalculatorDlg::OnBnClickedButtonThree()
{
// TODO: ここにコントロール通知ハンドラー コードを追加します。
HandleNumberClick(_T("3"));
}
void CMyCalculatorDlg::OnBnClickedButtonFour()
{
// TODO: ここにコントロール通知ハンドラー コードを追加します。
HandleNumberClick(_T("4"));
}
void CMyCalculatorDlg::OnBnClickedButtonFive()
{
// TODO: ここにコントロール通知ハンドラー コードを追加します。
HandleNumberClick(_T("5"));
}
void CMyCalculatorDlg::OnBnClickedButtonSix()
{
// TODO: ここにコントロール通知ハンドラー コードを追加します。
HandleNumberClick(_T("6"));
}
void CMyCalculatorDlg::OnBnClickedButtonSeven()
{
// TODO: ここにコントロール通知ハンドラー コードを追加します。
HandleNumberClick(_T("7"));
}
void CMyCalculatorDlg::OnBnClickedButtonEight()
{
// TODO: ここにコントロール通知ハンドラー コードを追加します。
HandleNumberClick(_T("8"));
}
void CMyCalculatorDlg::OnBnClickedButtonNine()
{
// TODO: ここにコントロール通知ハンドラー コードを追加します。
HandleNumberClick(_T("9"));
}数字ボタンの実装は以上の通りです
次は、小数点ボタンの処理について実装します
コメント