MFC学习记录 实现简易计算器

 

计算器的界面设计如上图所示

大致程序过程如下

按下数字键:

执行NumBottunDown( char  num);

该函数会把按钮相对应的数字 (char num) 加入要显示的数字 (m_num) 中去

然后把运算符按下的标记置为false

按下运算符键:

执行OptBottunDown(char OprtCome);

该函数先做判断是否连续按下了运算符的按钮

如果是的,就不执行操作

如果不是,就先把运算符按下的标记置为true,然后将按出的数字压入数字栈,再进入OprtAction(OprtCome) 该函数会根据优先级来做相应操作,OprtAction 函数还会调用Calculation(double a, double b, char oprt) 来进行进一步的运算

完成运算后再进行一系列初始化

按下等号键:

执行MakeAnswer();

该函数会把最后的结果算出来同时会清除数据

按下正负键:

判断正负标志

标志为true,则删除m_num最前面的一个字符

标志为false,则在m_num的最前面加入负号

判断整除0的情况:

Calculation(double a, double b, char oprt) 这个函数当oprt为 除号的时候会做一次判断,看除数是否为0,若为0则将错误标志m_IsError置为 1

然后所有运算符按钮的函数在进入之后都会先做一个判断,看错误标志是否为0,如果不是0就进入ShowError()函数来显示错误

下面是代码:

头文件:


// CalculatorDlg.h: 头文件
//

#pragma once
#include <vector>

// CCalculatorDlg 对话框
class CCalculatorDlg : public CDialogEx
{
// 构造
public:
	CCalculatorDlg(CWnd* pParent = nullptr);	// 标准构造函数

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_CALCULATOR_DIALOG };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持


// 实现
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:
	CString NumBottunDown(char num);//按下数字
	void OptBottunDown(char oprt);	//按下运算符
	void NumInStack();				//数字入栈
	void OprtAction(char OprtCome);	//运算符操作
	void MakeAnswer();				//获取最后结果
	double Calculation(double a, double b, char oprt);
	int icp(char oprt);	//栈外符号优先级
	int isp(char oprt);	//栈内符号优先级
	void ShowError();	//显示错误
	
private:
	CString m_display;	//要显示的数
	CString m_num;		//按键产生的数
	CString m_answer;	//存储最后一次产生的结果,初值为0
	bool m_IsDot;		//是否按下小数点
	bool m_IsNegative;	//是否是负数
	bool m_IsOprtBtnDown;//是否按下运算符,要初始化为true,目的是为了产生负数
	std::vector<double> m_NumStack;	//数字栈
	std::vector<char> m_OprtStack;	//符号栈
	int m_IsError;//错误标志
public:
	afx_msg void OnBnClickedButton1();
	afx_msg void OnBnClickedButton2();
	afx_msg void OnBnClickedButton3();
	afx_msg void OnBnClickedButton4();
	afx_msg void OnBnClickedButton5();
	afx_msg void OnBnClickedButton6();
	afx_msg void OnBnClickedButton7();
	afx_msg void OnBnClickedButton8();
	afx_msg void OnBnClickedButton9();
	afx_msg void OnBnClickedButton0();
	afx_msg void OnBnClickedButtondot();
	afx_msg void OnBnClickedButtonadd();
	afx_msg void OnBnClickedButtonsub();
	afx_msg void OnBnClickedButtonmut();
	afx_msg void OnBnClickedButtondiv();
	afx_msg void OnBnClickedButtonequ();
	afx_msg void OnBnClickedButtonallcln();
	afx_msg void OnBnClickedButtoncln2();
	afx_msg void OnBnClickedButtonneg();
};

源文件:


// CalculatorDlg.cpp: 实现文件
//

#include "stdafx.h"
#include "Calculator.h"
#include "CalculatorDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
//这里删除掉了系统自动上生成的 “关于” 对话框的实现

// CCalculatorDlg 对话框


CCalculatorDlg::CCalculatorDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_CALCULATOR_DIALOG, pParent)
	, m_display("")
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
//	m_NumStack.push_back(0);
	m_OprtStack.push_back('#');
	m_IsDot = false;
	m_IsNegative = false;
	m_IsOprtBtnDown = false;
	m_IsError = 0;
}

void CCalculatorDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_EDIT1, m_display);
}

BEGIN_MESSAGE_MAP(CCalculatorDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON1, &CCalculatorDlg::OnBnClickedButton1)
	ON_BN_CLICKED(IDC_BUTTON2, &CCalculatorDlg::OnBnClickedButton2)
	ON_BN_CLICKED(IDC_BUTTON3, &CCalculatorDlg::OnBnClickedButton3)
	ON_BN_CLICKED(IDC_BUTTON4, &CCalculatorDlg::OnBnClickedButton4)
	ON_BN_CLICKED(IDC_BUTTON5, &CCalculatorDlg::OnBnClickedButton5)
	ON_BN_CLICKED(IDC_BUTTON6, &CCalculatorDlg::OnBnClickedButton6)
	ON_BN_CLICKED(IDC_BUTTON7, &CCalculatorDlg::OnBnClickedButton7)
	ON_BN_CLICKED(IDC_BUTTON8, &CCalculatorDlg::OnBnClickedButton8)
	ON_BN_CLICKED(IDC_BUTTON9, &CCalculatorDlg::OnBnClickedButton9)
	ON_BN_CLICKED(IDC_BUTTON0, &CCalculatorDlg::OnBnClickedButton0)
	ON_BN_CLICKED(IDC_BUTTONflag, &CCalculatorDlg::OnBnClickedButtondot)
	ON_BN_CLICKED(IDC_BUTTONadd, &CCalculatorDlg::OnBnClickedButtonadd)
	ON_BN_CLICKED(IDC_BUTTONmin, &CCalculatorDlg::OnBnClickedButtonsub)
	ON_BN_CLICKED(IDC_BUTTONmut, &CCalculatorDlg::OnBnClickedButtonmut)
	ON_BN_CLICKED(IDC_BUTTONdiv, &CCalculatorDlg::OnBnClickedButtondiv)
	ON_BN_CLICKED(IDC_BUTTONequ, &CCalculatorDlg::OnBnClickedButtonequ)
	ON_BN_CLICKED(IDC_BUTTONcln, &CCalculatorDlg::OnBnClickedButtonallcln)
	ON_BN_CLICKED(IDC_BUTTONcln2, &CCalculatorDlg::OnBnClickedButtoncln2)
	ON_BN_CLICKED(IDC_BUTTONneg, &CCalculatorDlg::OnBnClickedButtonneg)
END_MESSAGE_MAP()


// CCalculatorDlg 消息处理程序

BOOL CCalculatorDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != nullptr)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	ShowWindow(SW_MINIMIZE);

	// TODO: 在此添加额外的初始化代码

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CCalculatorDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CCalculatorDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CCalculatorDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


CString CCalculatorDlg::NumBottunDown(char num)
{
	m_IsOprtBtnDown = false;
	return m_num += num;
}


void CCalculatorDlg::OptBottunDown(char OprtCome)
{
	//若不是已经按下运算符按钮
	if (!m_IsOprtBtnDown) {
		NumInStack();			//将数字入栈
		OprtAction(OprtCome);	//根据操作符及其优先级选择操作
		m_IsOprtBtnDown = true;
		//把要显示的数初始化
		m_IsNegative = false;
		m_IsDot = false;
		m_num = "";
	}
}


void CCalculatorDlg::NumInStack()
{
	double tmp;
	if (!m_num.IsEmpty()) {
		tmp = _wtof(m_num);
		m_NumStack.push_back(tmp);
	}
	else {
		tmp = _wtof(m_answer);
		m_NumStack.push_back(tmp);
	}
}


void CCalculatorDlg::OprtAction(char OprtCome)
{
	//若优先级栈内大于栈外,且数字栈中有 2 个以上的数字,就进行运算
	while (isp( m_OprtStack.back() ) > icp(OprtCome) && m_NumStack.size() >= 2)
	{
		double a, b;
		//弹出两个数
		b = m_NumStack.back();
		m_NumStack.pop_back();
		a = m_NumStack.back();
		m_NumStack.pop_back();
		//做计算然后将结果压入数字栈
		m_NumStack.push_back(Calculation( a, b, m_OprtStack.back() ));
		//符号弹出
		m_OprtStack.pop_back();
	}
	//符号入栈
	m_OprtStack.push_back(OprtCome);
}


void CCalculatorDlg::MakeAnswer()
{
	m_answer.Format( _T("%g"), m_NumStack.back() );	//先存下结果
	OnBnClickedButtonallcln();	//再清除数据
	m_display  = m_answer;		//再显示数据
}


double CCalculatorDlg::Calculation(double a, double b, char oprt)
{
	switch (oprt)
	{
	case '+': return a + b;
	case '-': return a - b;
	case '*': return a * b;
	case '/': 
		if (b == 0.0 && oprt == '/') {//出现除0
			m_IsError = 1;
//			m_OprtStack.push_back('#');
			return 0;
		}
		return a / b;
	default:
		return 0;
		break;
	}
}


//in coming Priority
int CCalculatorDlg::icp(char oprt)
{
	switch (oprt) {
	case '*':
	case '/': return 4;
	case '+':
	case '-': return 2;
	case '(': return 6;
	case ')': return 1;
	default: return 0;
	}
}

//in stack Priority
int CCalculatorDlg::isp(char oprt)
{
	switch (oprt) {
	case '*':
	case '/': return 5;
	case '+':
	case '-': return 3;
	case '(': return 1;
	case ')': return 6;
	default: return 0;
	}
}


void CCalculatorDlg::ShowError()
{
	switch (m_IsError)
	{
	case 1:
		OnBnClickedButtonallcln();
		m_display = "除数不能为0!";
		break;
	default:
		break;
	}
}


void CCalculatorDlg::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	m_display = NumBottunDown('1');
	UpdateData(FALSE);
}


void CCalculatorDlg::OnBnClickedButton2()
{
	// TODO: 在此添加控件通知处理程序代码
	m_display = NumBottunDown('2');
	UpdateData(FALSE);
}


void CCalculatorDlg::OnBnClickedButton3()
{
	// TODO: 在此添加控件通知处理程序代码
	m_display = NumBottunDown('3');
	UpdateData(FALSE);
}


void CCalculatorDlg::OnBnClickedButton4()
{
	// TODO: 在此添加控件通知处理程序代码
	m_display = NumBottunDown('4');
	UpdateData(FALSE);
}


void CCalculatorDlg::OnBnClickedButton5()
{
	// TODO: 在此添加控件通知处理程序代码
	m_display = NumBottunDown('5');
	UpdateData(FALSE);
}


void CCalculatorDlg::OnBnClickedButton6()
{
	// TODO: 在此添加控件通知处理程序代码
	m_display = NumBottunDown('6');
	UpdateData(FALSE);
}


void CCalculatorDlg::OnBnClickedButton7()
{
	// TODO: 在此添加控件通知处理程序代码
	m_display = NumBottunDown('7');
	UpdateData(FALSE);
}


void CCalculatorDlg::OnBnClickedButton8()
{
	// TODO: 在此添加控件通知处理程序代码
	m_display = NumBottunDown('8');
	UpdateData(FALSE);
}


void CCalculatorDlg::OnBnClickedButton9()
{
	// TODO: 在此添加控件通知处理程序代码
	m_display = NumBottunDown('9');
	UpdateData(FALSE);
}



void CCalculatorDlg::OnBnClickedButton0()
{
	// TODO: 在此添加控件通知处理程序代码
	m_display = NumBottunDown('0');
	UpdateData(FALSE);
}


void CCalculatorDlg::OnBnClickedButtondot()
{
	// TODO: 在此添加控件通知处理程序代码
	if (!m_IsDot)
	{
		m_num += '.';
		m_IsDot = true;
		m_display = m_num;
		UpdateData(FALSE);
	}
}

//addition
void CCalculatorDlg::OnBnClickedButtonadd()
{
	// TODO: 在此添加控件通知处理程序代码
	OptBottunDown('+');
	if (!m_IsError)
		m_display.Format(_T("%g"), m_NumStack.back());//要更新显示最新的数据
	else
		ShowError();
	UpdateData(FALSE);
}

//subtration
void CCalculatorDlg::OnBnClickedButtonsub()
{
	// TODO: 在此添加控件通知处理程序代码
	OptBottunDown('-');
	if (!m_IsError)
		m_display.Format(_T("%g"), m_NumStack.back());//要更新显示最新的数据
	else
		ShowError();
	UpdateData(FALSE);
}

//mutiplication
void CCalculatorDlg::OnBnClickedButtonmut()
{
	// TODO: 在此添加控件通知处理程序代码
	OptBottunDown('*');
	if (!m_IsError)
		m_display.Format(_T("%g"), m_NumStack.back());//要更新显示最新的数据
	else
		ShowError();
	UpdateData(FALSE);
}

//division
void CCalculatorDlg::OnBnClickedButtondiv()
{
	// TODO: 在此添加控件通知处理程序代码
	OptBottunDown('/');
	if (!m_IsError)
		m_display.Format(_T("%g"), m_NumStack.back());//要更新显示最新的数据
	else
		ShowError();
	UpdateData(FALSE);
}

//equal
void CCalculatorDlg::OnBnClickedButtonequ()
{
	// TODO: 在此添加控件通知处理程序代码
	if (m_IsOprtBtnDown) m_OprtStack.pop_back();//如果多输入了一个运算符,将其去除
	OptBottunDown('=');	//获得最终结果
	if (!m_IsError)
		MakeAnswer();	//将最终结果保留自m_num中,并且要清除其他数据
	else
		ShowError();
	UpdateData(FALSE);
}

//allclean
void CCalculatorDlg::OnBnClickedButtonallcln()
{
	// TODO: 在此添加控件通知处理程序代码
	m_display = "";
	m_num = "";
	if (!m_NumStack.empty()) m_NumStack.clear();
	if (!m_OprtStack.empty()) m_OprtStack.clear();
	m_NumStack.push_back(0);
	m_OprtStack.push_back('#');
	m_IsDot = false;
	m_IsNegative = false;
	m_IsOprtBtnDown = false;
	m_IsError = 0;
	UpdateData(FALSE);
}

//clean
void CCalculatorDlg::OnBnClickedButtoncln2()
{
	// TODO: 在此添加控件通知处理程序代码
	m_display = "";
	m_num = "";
	m_IsDot = false;
	m_IsNegative = false;
//	m_IsOprtBtnDown = false;
	UpdateData(FALSE);
}


void CCalculatorDlg::OnBnClickedButtonneg()
{
	// TODO: 在此添加控件通知处理程序代码
	if (m_IsNegative)
	{
		m_IsNegative = !m_IsNegative;
		m_num = m_num.Mid(1);
	}
	else
	{
		m_IsNegative = !m_IsNegative;
		m_num = '-' + m_num;
	}
	m_display = m_num;
	UpdateData(FALSE);
}

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值