mfc计算器实现

基于vs和标准C++的MFC计算器实现。

一、需求实现

1、功能

数据类型:正负数、小数。

非特殊功能(运算功能):+, - , *, /, %(百分号), ^(幂次方), | |(绝对值),!(阶乘)。其他符号:( )

特殊功能:C(清0),delete(退格),=(计算并显示结果)

2、方法

符号优先级处理方法:符号等级制

运算表达式处理方法:后缀表达式法

后缀表达式转换及计算辅助方法:符号栈、数字栈

3、用户界面

在这里插入图片描述

二、设计实现

这里主要讲解,MFC应用的实现。

1、MFC用户界面设计

输入区:Edit Control 控件
输出区:Static Text 控件
按钮区:Button 控件

2、MFC用户界面事件响应
(1)非特殊功能按钮 - 事件处理

自定义函数用于处理按钮操作时,向输入区追加按钮文本内容。实现非功能按钮事件的代码复用。

//MFC_CalculatorDlg.cpp: 实现文件

// 输入区显示按钮操作
void CMFCCalculatorDlg::AddToEditExp(UINT IDC_Button)
{
	CString strBtn;
	CString strExp;
	GetDlgItem(IDC_Button)->GetWindowText(strBtn);
	GetDlgItem(IDC_EDIT_EXP)->GetWindowText(strExp);
	SetDlgItemText(IDC_EDIT_EXP, strExp + strBtn);
}

数字、数字符号、运算表达式符号,为非特殊功能区,只为向输入区显示输入内容,无特殊功能。
其按钮事件处理如下: ------(只列出‘+’和’0’按钮事件处理,其他同理)

//‘+’加法,按钮事件处理
void CMFCCalculatorDlg::OnBnClickedButtonAdd()
{
	//调用自定义处理函数,传递‘+’按钮句柄
	AddToEditExp(IDC_BUTTON_ADD);
}

//‘0’数字,按钮事件处理
void CMFCCalculatorDlg::OnBnClickedButton0()
{
	AddToEditExp(IDC_BUTTON_0);
}
(2)特殊功能按钮 - 事件处理

‘C’清0,按钮事件处理

// ‘C/CE’清0,按钮事件处理
void CMFCCalculatorDlg::OnBnClickedButtonClear()
{
	SetDlgItemText(IDC_EDIT_EXP, NULL);
	CString cstr;
	cstr = "0";
	SetDlgItemText(IDC_STATIC_RESULT, cstr);
}

‘delete’退格,按钮事件处理

// ‘delete’退格,按钮事件处理
void CMFCCalculatorDlg::OnBnClickedButtonDelete()
{
	CString strExp;
	GetDlgItem(IDC_EDIT_EXP)->GetWindowText(strExp);
	strExp = strExp.Left(strExp.GetLength() - 1);
	SetDlgItemText(IDC_EDIT_EXP, strExp);
}

‘=’等于,按钮事件处理

//‘=’等于,按钮事件处理
void CMFCCalculatorDlg::OnBnClickedButtonEqual()
{
	CString strExp;
	Calculator cal;		//外部计算类
	CString cstr_Result;
	CString cstr_ErrorInfo;

	GetDlgItem(IDC_EDIT_EXP)->GetWindowText(strExp);
	string infix(CW2A(strExp.GetString()));
	cal.calculate(infix);
	cstr_Result.Format(_T("%f"), cal.getResult());
	
	//可用于外部计算类的异常信息传递到mfc用户界面	
	/*
	*cstr_ErrorInfo + cal.getErrorImfo().c_str();
	*if (!cstr_ErrorInfo.IsEmpty()) {
	*	SetDlgItemText(IDC_STATIC_RESULT, cstr_ErrorInfo);
	*}
	*/
	
	//输出区显示计算结果
	SetDlgItemText(IDC_STATIC_RESULT, cstr_Result);
}
3、外部计算器类(计算方法类)

Caculator.h: 头文件

//Caculator.h: 头文件
#include <stack>
#include <vector>
#include <string>
using namespace std;

//计算器类
class Calculator
{
public:
	Calculator();
	void calculate(string infix);		//计算方法
	void getFormat(string infix);		//表达式自定义标准格式化
	int getPrior(char c);				//获取算术符号优先级
	void getPostfix();					//后缀表达式转换
	void calResult();					//计算结果
	double getResult();					//获取结果
	//string getErrorImfo();				//获取异常信息
	string operatorSym;					//运算符号

private:
	vector<string> postfix;				//后缀表达式向量
	stack<char> symStack;				//符号栈
	stack<double> figStack;				//数字栈
	string stdInfix;					//自定义标准格式化表达式
	double result;						//最终计算结果
	//string cal_ErrorImfo;					//用于向外传递异常信息
};

Caculator.cpp: 实现文件

//Caculator.cpp: 实现文件
#include "pch.h"
#include "Calculator.h"

#include <stack>
#include <vector>
#include <string>
#include <cmath>

//const int MAX_EXP_LEN = 100;			//最大表达式长度

using namespace std;

//绝对值符号个数的奇偶性
enum ABS_ODEVITY {
	ABS_ODD = 1,
	ABS_EVEN = 2,
};

//算术符号优先权等级
enum PRIO_LV {
	PRIO_LV0 = 0,
	PRIO_LV1 = 1,
	PRIO_LV2 = 2,
	PRIO_LV3 = 3,
	PRIO_LV4 = 4,
};


Calculator::Calculator() {				//构造函数,初始化成员变量

	result = 0.0;
	//cal_ErrorImfo = "";
}


//表达式自定义标准格式化
void Calculator::getFormat(string infix) {

	stdInfix = infix;

	//实现正负数
	//for (int i = 0; i < stdInfix.length(); i++) {					//string下标调用运算符时可能会导致类型溢出
	for (size_t i = 0; i < stdInfix.size(); i++) {					//string.size()返回size_type类型,避免下标运算时的类型溢出
		if (stdInfix[i] == '-' || stdInfix[i] == '+') {				//-x转换为0-x,+x转化为0+x
			if (i == 0) {
				stdInfix.insert(0, 1, '0');
			}
			else if (stdInfix[i - 1] == '(') {
				stdInfix.insert(i, 1, '0');
			}
		}
	}
}

//获取算术符号优先级
int Calculator::getPrior(char c) {

	if (c == '+' || c == '-') {
		return PRIO_LV1;
	}
	else if (c == '*' || c == '/') {
		return PRIO_LV2;
	}
	else if (c == '%' || c == '^') {
		return PRIO_LV3;
	}
	else if (c == '!') {
		return PRIO_LV4;
	}
	else {
		return PRIO_LV0;
	}
	//else { cout << c << 非法符号! << endl; }
}

//后缀表达式转换
void Calculator::getPostfix() {

	int absNumeber = ABS_ODD;				//绝对值符号个数的奇偶性
	string tmp;

	//for (int i = 0; i < stdInfix.length(); i++) {
	for (size_t i = 0; i < stdInfix.size(); i++) {					//string.size()返回size_type类型,避免下标运算时的类型溢出
		tmp = "";
		switch (stdInfix[i]) {
		case '+':
		case '-':
		case '*':
		case '/':
		case '%':
		case '^':
		case '!':
			if (symStack.empty() || symStack.top() == '(' || symStack.top() == '[' || symStack.top() == '{' || (symStack.top() == '|' && absNumeber == ABS_ODD)) {
				symStack.push(stdInfix[i]);
			}
			else {
				while (!symStack.empty() && (getPrior(symStack.top()) >= getPrior(stdInfix[i]))) {
					tmp += symStack.top();
					postfix.push_back(tmp);
					symStack.pop();
					tmp = "";
				}
				symStack.push(stdInfix[i]);
			}
			break;
		case '|':
			if (absNumeber == ABS_ODD) {
				symStack.push(stdInfix[i]);
				absNumeber = ABS_EVEN;
			}
			else {
				while (!symStack.empty() && symStack.top() != '|') {
					tmp += symStack.top();
					postfix.push_back(tmp);
					symStack.pop();
					tmp = "";
				}
				if (!symStack.empty() && symStack.top() == '|') {
					tmp += symStack.top();
					postfix.push_back(tmp);						//左绝对值符号'|'加入后缀表达式,用于绝对值的检测计算
					symStack.pop();
					absNumeber = ABS_ODD;
				}
			}
			break;
		case '(':
		case '[':
		case '{':
			symStack.push(stdInfix[i]);
			break;
		case ')':
			while (!symStack.empty() && symStack.top() != '(') {
				tmp += symStack.top();
				postfix.push_back(tmp);
				symStack.pop();
				tmp = "";
			}
			if (!symStack.empty() && symStack.top() == '(') {
				symStack.pop();							//将左括号出栈丢弃
			}
			break;
		case ']':
			while (!symStack.empty() && symStack.top() != '[') {
				tmp += symStack.top();
				postfix.push_back(tmp);
				symStack.pop();
				tmp = "";
			}
			if (!symStack.empty() && symStack.top() == '[') {
				symStack.pop();							//将左括号出栈丢弃
			}
			break;
		case '}':
			while (!symStack.empty() && symStack.top() != '{') {
				tmp += symStack.top();
				postfix.push_back(tmp);
				symStack.pop();
				tmp = "";
			}
			if (!symStack.empty() && symStack.top() == '{') {
				symStack.pop();							//将左括号出栈丢弃
			}
			break;
		default:
			if ((stdInfix[i] >= '0' && stdInfix[i] <= '9')) {
				tmp += stdInfix[i];
				while (i + 1 < stdInfix.length() && (stdInfix[i + 1] >= '0' && stdInfix[i + 1] <= '9' || stdInfix[i + 1] == '.')) {		//小数处理

					tmp += stdInfix[i + 1];			//是连续的数字,则追加
					i++;
				}
				if (tmp[tmp.length() - 1] == '.') {
					tmp += '0';						//将x.做x.0处理
				}
				postfix.push_back(tmp);
			}
			break;
		}//end switch
	}//end for

	//if(!symStack.empty()) {
	while (!symStack.empty()) {						//将栈中剩余符号加入后缀表达式
		tmp = "";
		tmp += symStack.top();
		postfix.push_back(tmp);
		symStack.pop();
	}
}

//获取运算结果
void Calculator::calResult() {

	string tmp;
	double number = 0;
	double op1 = 0, op2 = 0;

	for (int i = 0; i < postfix.size(); i++) {
		tmp = postfix[i];
		if (tmp[0] >= '0' && tmp[0] <= '9') {
			number = atof(tmp.c_str());
			figStack.push(number);
		}
		else if (postfix[i] == "+") {
			if (!figStack.empty()) {
				op2 = figStack.top();
				figStack.pop();
			}
			if (!figStack.empty()) {
				op1 = figStack.top();
				figStack.pop();
			}
			figStack.push(op1 + op2);
		}
		else if (postfix[i] == "-") {
			if (!figStack.empty()) {
				op2 = figStack.top();
				figStack.pop();
			}
			if (!figStack.empty()) {
				op1 = figStack.top();
				figStack.pop();
			}
			figStack.push(op1 - op2);
		}
		else if (postfix[i] == "*") {
			if (!figStack.empty()) {
				op2 = figStack.top();
				figStack.pop();
			}
			if (!figStack.empty()) {
				op1 = figStack.top();
				figStack.pop();
			}
			figStack.push(op1 * op2);
		}
		else if (postfix[i] == "/") {
			if (!figStack.empty()) {
				op2 = figStack.top();
				figStack.pop();
			}
			if (!figStack.empty()) {
				op1 = figStack.top();
				figStack.pop();
			}
			if (op2 != 0) {
				///除数不为0,未做处理,默认
			}
			figStack.push(op1 / op2);
		}
		else if (postfix[i] == "%") {
			if (!figStack.empty()) {
				op2 = figStack.top();
				figStack.pop();
			}
			if (!figStack.empty()) {
				op1 = figStack.top();
				figStack.pop();
			}
			figStack.push(fmod(op1, op2));			//可进行小数求余
		}
		else if (postfix[i] == "^") {
			if (!figStack.empty()) {
				op2 = figStack.top();
				figStack.pop();
			}
			if (!figStack.empty()) {
				op1 = figStack.top();
				figStack.pop();
			}
			figStack.push(pow(op1, op2));
		}
		else if (postfix[i] == "|") {
			if (!figStack.empty()) {
				op1 = figStack.top();
				figStack.pop();
			}
			figStack.push(abs(op1));
		}
		else if (postfix[i] == "!") {
			if (!figStack.empty()) {
				op1 = figStack.top();
				figStack.pop();
			}
			if (op1 > 0) {
				//阶乘数应大于;为小数时(转化为整数求阶)
				double factorial = 1;
				for (int i = 1; i <= op1; ++i)
				{
					factorial *= i;
				}
				op1 = factorial;
			}
			figStack.push(op1);
		}
	}//end for
	if (!figStack.empty()) {
		result = figStack.top();
	}
}


//计算方法
void Calculator::calculate(string infix) {
	getFormat(infix);			//表达式自定义标准格式化
	getPostfix();				//后缀表达式转换
	calResult();				//计算结果
}

//获取结果
double Calculator::getResult() {
	return result;
}

/*
//获取异常信息
string Calculator::getErrorImfo() {
	return cal_ErrorImfo;
}
*/

资源获取

关于外部计算器类(计算方法类)的具体设计分析 请转 C++计算器实现 ——(完整功能实现、设计分析)

关于整个MFC_Caculator的程序包 及 项目设计说明书(含总结) csdn下载地址:MFC_Calculator.rar

百度网盘链接: https://pan.baidu.com/s/11jFpGv4AaTbSHog11w4bpw 提取码: 9bbq

MFC_Caculator项目:
在这里插入图片描述

  • 57
    点赞
  • 297
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 52
    评论
MFC(Microsoft Foundation Class)是微软公司开发的一种基于 Windows 操作系统的 C++ 类库,常用于 Windows 平台下的应用程序开发。下面是一个简单的 MFC 计算器实现步骤: 1. 创建一个 MFC 应用程序项目,选择“单文档”模板。 2. 在应用程序视图中添一个对话框,用于显示计算器界面。 3. 在对话框中添按钮,分别对应数字、运算符和功能键(如清空、等于、退格等)。 4. 在对话框类中添相应的变量和控件变量,用于实现计算器功能。 5. 在对话框类中添响应按钮点击事件的函数,实现计算器的逻辑。 6. 在应用程序类中设置主窗口为对话框,并启动应用程序。 下面是一个简单的 MFC 计算器的代码示例: ``` // CalculatorDlg.h 文件 class CCalculatorDlg : public CDialogEx { public: CCalculatorDlg(CWnd* pParent = nullptr); enum { IDD = IDD_CALCULATOR_DIALOG }; protected: virtual void DoDataExchange(CDataExchange* pDX); virtual BOOL OnInitDialog(); DECLARE_MESSAGE_MAP() private: CString m_strResult; double m_dOperand1, m_dOperand2; int m_nOperator; BOOL m_bNewNumber; void AppendNumber(int nNumber); void AppendOperator(int nOperator); void Calculate(); public: afx_msg void OnBnClickedBtn0(); afx_msg void OnBnClickedBtn1(); // 添其他数字按钮的响应函数 afx_msg void OnBnClickedBtnAdd(); afx_msg void OnBnClickedBtnSubtract(); // 添其他运算符按钮的响应函数 afx_msg void OnBnClickedBtnClear(); afx_msg void OnBnClickedBtnEqual(); afx_msg void OnBnClickedBtnBackspace(); // 添其他功能键按钮的响应函数 afx_msg void OnEnChangeEditResult(); }; // CalculatorDlg.cpp 文件 CCalculatorDlg::CCalculatorDlg(CWnd* pParent /*=nullptr*/) : CDialogEx(IDD_CALCULATOR_DIALOG, pParent) , m_strResult(_T("")) , m_dOperand1(0) , m_dOperand2(0) , m_nOperator(0) , m_bNewNumber(TRUE) { } void CCalculatorDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Text(pDX, IDC_EDIT_RESULT, m_strResult); } BOOL CCalculatorDlg::OnInitDialog() { CDialogEx::OnInitDialog(); m_strResult = "0"; UpdateData(FALSE); return TRUE; } void CCalculatorDlg::AppendNumber(int nNumber) { if (m_bNewNumber) { m_strResult = ""; m_bNewNumber = FALSE; } m_strResult += CString(nNumber + '0'); UpdateData(FALSE); } void CCalculatorDlg::AppendOperator(int nOperator) { if (!m_bNewNumber) { Calculate(); } m_dOperand1 = _ttof(m_strResult); m_nOperator = nOperator; m_bNewNumber = TRUE; } void CCalculatorDlg::Calculate() { m_dOperand2 = _ttof(m_strResult); switch (m_nOperator) { case IDC_BTN_ADD: m_dOperand1 += m_dOperand2; break; case IDC_BTN_SUBTRACT: m_dOperand1 -= m_dOperand2; break; // 添其他运算符的计算 } m_strResult.Format("%.2f", m_dOperand1); UpdateData(FALSE); } void CCalculatorDlg::OnBnClickedBtn0() { AppendNumber(0); } void CCalculatorDlg::OnBnClickedBtn1() { AppendNumber(1); } // 添其他数字按钮的响应函数 void CCalculatorDlg::OnBnClickedBtnAdd() { AppendOperator(IDC_BTN_ADD); } void CCalculatorDlg::OnBnClickedBtnSubtract() { AppendOperator(IDC_BTN_SUBTRACT); } // 添其他运算符按钮的响应函数 void CCalculatorDlg::OnBnClickedBtnClear() { m_strResult = "0"; m_dOperand1 = 0; m_dOperand2 = 0; m_nOperator = 0; m_bNewNumber = TRUE; UpdateData(FALSE); } void CCalculatorDlg::OnBnClickedBtnEqual() { Calculate(); } void CCalculatorDlg::OnBnClickedBtnBackspace() { if (m_bNewNumber) { return; } int nLength = m_strResult.GetLength(); if (nLength == 1 || (nLength == 2 && m_strResult[0] == '-')) { m_strResult = "0"; m_bNewNumber = TRUE; } else { m_strResult.Delete(nLength - 1, 1); } UpdateData(FALSE); } // 添其他功能键按钮的响应函数 void CCalculatorDlg::OnEnChangeEditResult() { if (!m_bNewNumber) { Calculate(); } } ``` 注意:代码中的 IDC_BTN_ADD、IDC_BTN_SUBTRACT 等都是控件 ID,需要在资源编辑器中设置。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Whitemeen太白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值