实现带有优先级的计算器
在原有代码基础上,稍加修改,利用堆栈实现四则运算
在.cpp文件中添加:
#include <stack>
using namespace std;
.h文件中定义:
public:
CString str; //用于存储编辑框中内容
CString LastResult1;
CString LastResult2;
CString TempStr;
.cpp文件中:
void CmyCalculatorDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT1, str);
DDX_Text(pDX, IDC_EDIT2, LastResult1);
DDX_Text(pDX, IDC_EDIT4, LastResult2);
}
设置运算符优先级:
int Lv(char m)
{
switch (m)
{
case '+':
return 1; break;
case '-':
return 1; break;
case '*':
return 2; break;
case '/':
return 2; break;
case '%':
return 2; break;
case '(':
return 0; break;
case ')':
return 0; break;
case '!':
return -1; break;
default:break;
}
}
对等号这个按键进行如下修改:
void CmyCalculatorDlg::OnBnClickedButton16() //"="
{
// TODO: 在此添加控件通知处理程序代码
stack<double> X; //堆栈1用作存数
stack<char> Y; //堆栈2用作存运算符
CString str2; //str2用作拼接多位数字
UpdateData(TRUE); //获取面板上的表达式
TempStr = str; //用于存储历史记录
LastResult2 = LastResult1;
LastResult1 = TempStr;
UpdateData(FALSE);
str += "!?"; //在表达式的末尾加上!?方便后面的操作
int i = 0; //i从0开始,用来检索表达式
int e = 0; //e用来记录表达式中左括号的数量
int f = 0; //f用来记录表达式中右括号的数量
double t; //t用来保存两个double运算后的结果
double q; //q用来保存string转换成double后的数
bool adc = true;
//开始对表达式进行入栈运算:
while (str[i] != '?')
{
if (str[i] > 47 && str[i] < 58 || str[i] == '.') //[0,9]和小数点
{
int F = 0; //F用来记录小数点的个数
for (i; str[i] > 47 && str[i] < 58 || str[i] == '.'; i++)
{
str2 += str[i];
if (str[i] == '.')
{
F++;
}
if (F > 1)
{
//MessageBox("一个数的小数点多于一个!");
SetDlgItemText(IDC_EDIT1, _T("一个数的小数点多于一个!"));
return;
}
}
q = _wtof(str2);
str2 = "";
X.push(q);
}
if (str[i] >= 40 && str[i] <= 47) //包括:'(' ')' '+' '-' '*' '/' '.' ','
{
if (i == 0 && str[i] == '-' && adc)
{
i++;
if (str[i] > 47 && str[i] < 58 || str[i] == '.') //[0,9]和小数点
{
int F = 0;
for (i; str[i] > 47 && str[i] < 58 || str[i] == '.'; i++) //遍历
{
str2 += str[i];
if (str[i] == '.')
{
F++;
}
if (F > 1)
{
// MessageBox("一个数的小数点多于一个!");
SetDlgItemText(IDC_EDIT1, _T("一个数的小数点多于一个!"));
return;
}
}
q = 0 - _wtof(str2);
str2 = "";
X.push(q);
i--;
}
else if (str[i] == '(') //‘(’ :40 ‘)’:41
{
adc = false;
double Q = 0;
X.push(Q);
i = -1;
}
}
else if (Y.empty() || str[i] == '(' || Lv(str[i]) > Lv(Y.top()))
{
Y.push(str[i]);
if (str[i + 1] == '-')
{
i = i + 2;
if (str[i] > 47 && str[i] < 58 || str[i] == '.') //[0,9]和小数点
{
int F = 0;
for (i; str[i] > 47 && str[i] < 58 || str[i] == '.'; i++)
{
str2 += str[i];
if (str[i] == '.')
{
F++;
}
if (F > 1)
{
SetDlgItemText(IDC_EDIT1, _T("一个数的小数点多于一个!"));
return;
}
}
q = 0 - _wtof(str2);
str2 = "";
X.push(q);
}
i--;
}
}
else
{
if (str[i] == ')')
{
for (; Y.top() != '('; Y.pop())
{
char f = Y.top();
double a = X.top();
if (a == 0 && f == '/' )
{
SetDlgItemText(IDC_EDIT1, _T("除数不能为0!"));
return;
}
X.pop();
double b = X.top();
X.pop();
switch (f)
{
case '+':t = b + a; break;
case '-':t = b - a; break;
case '*':t = b * a; break;
case '/':t = b / a; break;
default:break;
}
X.push(t);
}
Y.pop();
}
else
{
for (; !(Y.empty()) && Lv(str[i]) <= Lv(Y.top()); Y.pop())
{
char f = Y.top();
double a = X.top();
if (a == 0 && (f == '/' || f == '%'))
{
SetDlgItemText(IDC_EDIT1, _T("除数不能为0!"));
return;
}
X.pop();
double b = X.top();
X.pop();
switch (f)
{
case '+':t = b + a; break;
case '-':t = b - a; break;
case '*':t = b * a; break;
case '/':t = b / a; break;
default:break;
}
X.push(t);
}
Y.push(str[i]);
}
}
}
++i;
}
CString a;
double I = X.top();
X.pop();
a.Format(_T("%lf"), I);
SetDlgItemText(IDC_EDIT1, a);
}
成果:
本代码仍存在弊端,整个表达式必须要加括号才可以运算,否则运算括号里内容或输出最后输入的值,望大佬指点!