この章では、ルートボタンがおされたときの処理の説明をしていきます
処理概要
ルートボタンは、入力中の数字のルートを計算するときに使用します
このボタンを押すことで、入力した数字のルートを計算します
表示ディスプレイに表示されている数字のルートを計算し結果を表示します
場合に応じて、current_bufferやstack[0]の値の修正も行います
ルートボタンが押された位置で以下のことを考慮します
ケース1. ディスプレイの表示が空
ACボタンが押されたあとや電卓の起動時の状態をさします
(ディスプレイ、current_buffer、stack[0]、stack[1]がどれも空文字)
このときは、何も処理を実行しません
ケース2. 演算子を指定した直後
四則演算や=を押された直後、ディスプレイには演算結果が表示され、stack[0]にも演算結果が入っています
しかし、current_bufferは空文字です
このときは、ディスプレイの表示およびstack[0]の値のルート計算を実行します
前提条件
ルートボタンが押される直前の電卓は、処理概要および「考慮すること」に対して、それぞれどのような状態の場合があるかを考えてみます
| 演算子の表示部分 | 数値の表示部分 | current_buffer | stack[0] | 状態の説明 |
|---|---|---|---|---|
| 空 | 空 | 空 | 空 | ACボタン直後の状態 |
| 空 | 数値 | 数値 | 空 | 左辺値を入力している状態 |
| ―、+、×、÷、= | 数値 | 空 | 数値 | 演算子が押された後の状態 |
| ―、+、×、÷、= | 数値 | 数値 | 数値 | 右辺値を入力している状態 |
処理内容
ルートボタンのイベント処理フロー
- 現在入力中の数値の符号を反転
- もし
current_bufferに値が入っている場合(=数値入力中)、current_bufferの値のルート計算を実行する - 更新した
current_bufferの値をディスプレイに表示する
- もし
- 計算結果の符号を反転
- もし
current_bufferが空で、stack[0]に値が入っている場合(=計算結果が表示されている状態)、stack[0]の値のルート計算を実行する - 更新した
stack[0]の値をディスプレイに表示する
- もし
- 何もしない
- 上記以外の場合(例: 起動直後、ACボタン直後)は、何もしない
実装
イベントハンドラの設定
VisualC++の機能を使用して戻るボタンのイベントハンドラを作成します
作成されたイベントハンドラはafx_msg void OnBnClickedButtonRoot();です
その後、イベントハンドラに処理を記述していきます
1. MyCalculatorDlg.h
class CMyCalculatorDlg : public CDialogEx
{
// コンストラクション
public:
CMyCalculatorDlg(CWnd* pParent = nullptr); // 標準コンストラクター
// ダイアログ データ
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_MYCALCULATOR_DIALOG };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV サポート
// 実装
private:
void AddEditBoxText(LPCTSTR lpText);
void setEditBoxText(LPCTSTR lpText);
void initVariable();
void clickOperatorButton(LPCTSTR lpText);
void setOperatorText(LPCTSTR lpText);
void clearCurrentBuffer();
double calculate();
void HandleNumberClick(LPCTSTR number_char);
void disableButton();
void enableButton();
double IsNumberAndConvert(const TCHAR* lpText);
CString ConvertDoubleToCString(double result);
CString current_buffer = _T("");
CString last_operator = _T("");
CString stack[2] = {_T(""),_T("")};
protected:
HICON m_hIcon;
// 生成された、メッセージ割り当て関数
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedButtonAc();
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();
afx_msg void OnBnClickedButtonPlus();
afx_msg void OnBnClickedButton1Minus();
afx_msg void OnBnClickedButtonMulti();
afx_msg void OnBnClickedButtonDiv();
afx_msg void OnBnClickedButtonEqual();
afx_msg void OnBnClickedButtonDecimal();
afx_msg void OnBnClickedButtonBack();
afx_msg void OnBnClickedButtonSign();
afx_msg void OnBnClickedButtonRoot(); // ルートボタン
};2. MyCalculatorDlg.cpp
void CMyCalculatorDlg::OnBnClickedButtonRoot()
{
// TODO: ここにコントロール通知ハンドラー コードを追加します。
try {
double val;
if (current_buffer.IsEmpty())
{
if (stack[0].IsEmpty()) {
return;
}
double val = IsNumberAndConvert(stack[0]);
val = sqrt(val);
stack[0] = ConvertDoubleToCString(val);
setEditBoxText(stack[0]);
}
else {
double val = IsNumberAndConvert(current_buffer);
val = sqrt(val);
current_buffer = ConvertDoubleToCString(val);
setEditBoxText(current_buffer);
}
}
catch (const std::invalid_argument& e) {
CString str(e.what());
setEditBoxText(str);
disableButton();
}
}以上が、√(ルート)ボタンを実装したプログラムです
これで、**フェーズ1**、**フェーズ2**の実装が完了しました
次回は、テストと実装のまとめを行います
コメント