支持小数、阶乘、乘方、加减乘除、括号优先级运算,美化输出结果(显示结果末尾没有多余的0)
void CCaculator_LittleduckDlg::OnBnClickedButton12() // 在这里进行运算 最关键的代码
{
// TODO: 在此添加控件通知处理程序代码
CString editText;
GetDlgItemText(IDC_EDIT2, editText);
double ans = 0;
CString CString_ans("Sorry, but I do not know.");
int noans = 0;
CString operators ("$"); // 运算符栈
int operators_len = 1;
double numbers[100]={0}; // 数字栈
int numbers_len = 0;
const char pri[9][9] = { // [栈顶][当前] = 表示抵销 >表示计算 <表入栈 " "为匹配不成功
//------------当前运算符
// + - * / ^ ! ( ) $
// 0 1 2 3 4 5 6 7 8
/* + 0*/‘>‘,‘>‘,‘<‘,‘<‘,‘<‘,‘<‘,‘<‘,‘>‘,‘>‘,
/* 栈 - 1*/‘>‘,‘>‘,‘<‘,‘<‘,‘<‘,‘<‘,‘<‘,‘>‘,‘>‘,
/* 顶 * 2*/‘>‘,‘>‘,‘>‘,‘>‘,‘<‘,‘<‘,‘<‘,‘>‘,‘>‘,
/* 运 / 3*/‘>‘,‘>‘,‘>‘,‘>‘,‘<‘,‘<‘,‘<‘,‘>‘,‘>‘,
/* 算 ^ 4*/‘>‘,‘>‘,‘>‘,‘>‘,‘>‘,‘<‘,‘<‘,‘>‘,‘>‘,
/* 符 ! 5*/‘>‘,‘>‘,‘>‘,‘>‘,‘>‘,‘>‘,‘ ‘,‘>‘,‘>‘,
/* ( 6*/‘<‘,‘<‘,‘<‘,‘<‘,‘<‘,‘<‘,‘<‘,‘=‘,‘ ‘,
/* ) 7*/‘ ‘,‘ ‘,‘ ‘,‘ ‘,‘ ‘,‘ ‘,‘ ‘,‘ ‘,‘ ‘,
/* $ 8*/‘<‘,‘<‘,‘<‘,‘<‘,‘<‘,‘<‘,‘<‘,‘ ‘,‘=‘
};
CString tail("$");
editText += tail;
CString blank(" ");
CString mynum("0123456789.");
CString myoper("+-*/^!()$");
int digit = 0; // 当前数字位数
int point = 0; // 小数点个数
for(int i = 0; i < editText.GetLength(); ++i) // 开始处理这个字符串
{
if( editText[i] == blank ) // 空白则略过
{
continue;
}
else if(editText[i] == mynum[0] || editText[i] == mynum[1] ||
editText[i] == mynum[2] || editText[i] == mynum[3] ||
editText[i] == mynum[4] || editText[i] == mynum[5] ||
editText[i] == mynum[6] || editText[i] == mynum[7] ||
editText[i] == mynum[8] || editText[i] == mynum[9] ) // 数字处理
{
++ digit;
if (digit > 1) // 数字位数大于1,,则数字栈顶数字出栈,重新整理再入栈
{
CString temp = blank;
temp = editText[i];
numbers[ numbers_len - 1] = numbers[ numbers_len - 1] * 10 + _wtof(temp) ;
if(point > 0)
++ point; // 记录小数的位数
}
else // 数字入栈
{
++ numbers_len;
CString temp = blank;
temp = editText[i];
numbers[numbers_len -1] = _wtof(temp);
//* (numbers + numbers_len - 1) = atof(temp);
}
}
else if (editText[i] == mynum[10])
{
point = 1;
}
else // !!! 最重要的运算 = 表示抵销 >表示计算 <表入栈 " "为匹配不成功
{
digit = 0;
if (point > 0)
{
point --;
for(int tem = 0; tem < point; ++ tem)
numbers[ numbers_len - 1] = numbers[ numbers_len - 1] / 10; // 刚刚入栈的那个数调整其小数点
point = 0;
}
CString temp = blank;
temp = editText[i]; //当前运算符
int top = 0, cur = 0;
for(int a = 0; a < myoper.GetLength(); ++ a)
{
if( myoper[a] == temp )
{
cur = a;
}
if( myoper[a] == operators[operators_len - 1] )
{
top = a;
}
}
char cpri = pri[top][cur];
if(cpri == ‘<‘)//运算符入栈
{
++ operators_len;
operators += temp;
}
if(cpri == ‘>‘) // 计算 注意i的值在下一次不变 记得取出运算符
{
if(top < 5 && numbers_len < 2)
{
noans = 1;
break;
}
if(numbers_len > 1 && top < 5)
{
// 取出两个数
double number1, number2, number3 = 1;
number1 = numbers[ numbers_len - 2 ];
number2 = numbers[ numbers_len - 1 ];
// 进行运算
switch (top)
{
case 0: // + 运算
number3 = number1 + number2;
break;
case 1: // - 运算
number3 = number1 - number2;
break;
case 2: // * 运算
number3 = number1 * number2;
break;
case 3: // / 运算
number3 = number1 / number2;
break;
case 4: // ^ 运算
for(int te = 0; te < number2; ++ te)
{
number3 *= number1;
}
break;
}
// 把结果放回栈顶
-- numbers_len;
numbers[ numbers_len - 1 ] = number3;
//
//丢掉最后一个运算符
-- operators_len;
CString temp11("");
for(int l = 0; l < operators_len; ++ l)
{
temp11 += operators[l];
}
operators = temp11;
}
if(top == 5 && numbers_len > 0) // ! 运算 取出一个数做阶层运算 并把结果放回栈中
{
double number2, number3 = 1;
number2 = numbers[ numbers_len - 1 ];
-- operators_len;
CString temp11("");
for(int l = 0; l < operators_len; ++ l) // 丢掉最后一个运算符
{
temp11 += operators[l];
}
operators = temp11;
for (int te = 1; te <= number2; te++)
{
number3 *= te;
}
if(number2 == 0)
{
number3 = 1;
}
numbers[ numbers_len - 1 ] = number3;
}
-- i;
}
if(cpri == ‘=‘) // 运算符抵销
{
-- operators_len;
CString temp11("");
for(int l = 0; l < operators_len; ++ l) // 丢掉最后一个运算符
{
temp11 += operators[l];
}
operators = temp11;
}
if(cpri == ‘ ‘) // 运算符不匹配 终止运算并显示Sorry, but I do not know.
{
noans = 1;
break;
}
}
}
if (numbers_len == 1 && operators_len == 0 && noans == 0)
{
ans = numbers[ numbers_len - 1];
CString_ans.Format(L"%f", ans);
int point = 0;
CString cpoint(".");
CString blank("0");
for (int i = 0; i < CString_ans.GetLength(); i++)
{
if(CString_ans[i] == cpoint)
{
point = i;
break;
}
}
if(point > 0)
{
for (int i = CString_ans.GetLength() - 1; i >= point; i--)
{
if(CString_ans[i] != blank)
{
CString mystr("");
for(int k = 0; k < i; ++k)
{
mystr += CString_ans[k];
}
if(i > point)
{
mystr += CString_ans[i];
}
CString_ans = mystr;
break;
}
}
}
}
if(noans == 1 || numbers_len > 1 || operators_len > 0)
{
CString_ans = "Sorry, but I do not know.";
}
SetDlgItemText(IDC_EDIT2, CString_ans);