基于vs和标准C++的MFC计算器实现。
数据类型:正负数、小数。
非特殊功能(运算功能):+, - , *, /, %(百分号), ^(幂次方), | |(绝对值),!(阶乘)。其他符号:( )
特殊功能:C(清0),delete(退格),=(计算并显示结果)
符号优先级处理方法:符号等级制
运算表达式处理方法:后缀表达式法
后缀表达式转换及计算辅助方法:符号栈、数字栈
这里主要讲解,MFC应用的实现。
输入区:Edit Control 控件
输出区:Static Text 控件
按钮区:Button 控件
自定义函数用于处理按钮操作时,向输入区追加按钮文本内容。实现非功能按钮事件的代码复用。
//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);
}
‘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);
}
Caculator.h: 头文件
//Caculator.h: 头文件
#include
#include
#include
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
#include
#include
#include
//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