この章では、+/-ボタンがおされたときの処理の説明をしていきます
処理概要
+/‐ボタンは、入力中の数字の符号を切り替えるときに使用します
このボタンを押すことで、入力した数字の符号を反転します
表示ディスプレイに表示されている数字の先頭に切り替えた符号を表示します
ただし、+(プラス)の記号は表示しません
場合に応じて、current_bufferやstack[0]、stack[1]の値の修正も行います
+/-ボタンが押された位置で以下のことを考慮します
ケース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 OnBnClickedButtonSign();です
その後、イベントハンドラに処理を記述していきます
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(); // +/-ボタン
};2. MyCalculatorDlg.cpp
void CMyCalculatorDlg::OnBnClickedButtonSign()
{
// TODO: ここにコントロール通知ハンドラー コードを追加します。
try {
double val;
if (current_buffer.IsEmpty())
{
if (stack[0].IsEmpty()) {
return;
}
val = IsNumberAndConvert(stack[0]);
val = val * -1;
stack[0] = ConvertDoubleToCString(val);
setEditBoxText(stack[0]);
}
else {
val = IsNumberAndConvert(current_buffer);
val = val * -1;
current_buffer = ConvertDoubleToCString(val);
setEditBoxText(current_buffer);
}
}
catch (const std::invalid_argument& e) {
CString str(e.what());
setEditBoxText(str);
disableButton();
}
}以上が、+/-ボタンを実装したプログラムです
次回は√(ルート)ボタンの処理を実装します
コメント