栈应用之中缀表达式计算C#实现

时间:2022-04-25 00:23:46

支持小数、阶乘、乘方、加减乘除、括号优先级运算,美化输出结果(显示结果末尾没有多余的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);