总体思路:需要用到栈,从中缀表达式到后缀表达式,再把后缀表达式转化为结果,比如计算9+(3-1)*5+4/2,这个式子就叫做中缀表达式,然后我们需要把它转化成后缀表答式,方法:将中缀表达式从左到右读取,如果是数字,直接输出到后缀表达式,如果是字符,则如果是右括号,把从栈顶开始到栈中左括号的字符输出到后缀表达式,如果是运算符,优先级不比栈顶元素(只能是字符,遇到括号停止)高的,输出到后缀表达式,当读取完后,栈还有剩余,全部从栈顶输出到后缀表达式,这样,后缀表达式就是931-5*+42/+;
然后把后缀表达式转化为结果,方法:从左到右读取后缀表达式,如果是数字,则进栈,如果是运算符#,把栈顶的第一个字符取出来当作a,再把栈顶的第二个取出来当作b,进行b#a的运算,再把结果放进栈,知道读取完毕后,栈中的数字就是答案。
所以,在中缀表达式转换到后缀表达式中,我们可以用a栈存后缀表达式中的数字,b栈存还没处理完毕的运算符,当有运算符要输出到后缀表达式了,马上用a栈的前两个字母进行运算即可。下面的代码支持输入小数。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<string>
#include<algorithm>
using namespace std;
stack<char> a;//存运算符
stack<double> b;//存数字
void calulate(char to)//运算符输出到后缀表达式时,进行运算
{
double x = b.top();
b.pop();
double y = b.top();
b.pop();
switch (to)
{
case '+':b.push(y + x); break;
case '-':b.push(y - x); break;
case '*':b.push(y*x); break;
case '/':b.push(y / x); break;
}
}
int main()
{
char s[1000];
while (cin >> s)
{
while (!a.empty())
a.pop();
while (!b.empty())
b.pop();
int len = strlen(s);
int ans = 0;
for (int i = 0; i < len; i++)//逐个读取中缀表达式
{
if (s[i] == '.')//处理小数点
{
double d = b.top();
b.pop();
i++;
int ant = 1;
while (s[i] >= '0'&&s[i] <= '9')
{
double dd = s[i] - '0';
for (int j = 0; j < ant; j++)
dd = dd / 10.0;
ant++;
d += dd;
i++;
}
b.push(d);
i--;
}
else if (s[i] >= '0'&&s[i] <= '9')
{
double d = s[i] - '0';
i++;
while (s[i] >= '0'&&s[i] <= '9')//处理十位以上的数字
{
d = d*10.0 + s[i] - '0';
i++;
}
i--;
b.push(d);
}
else
{
if (s[i] == '(')//左括号必须加入栈
a.push(s[i]);
else
{
if (a.empty())//空栈即把其加入
{
a.push(s[i]);
}
else
{
if (s[i] == ')')//右括号时,把直到左括号的符号输出,即进行运算
{
while (a.top() != '(')
{
calulate(a.top());
a.pop();
}
a.pop();
}
else
{
if (s[i] == '+' || s[i] == '-')//+或-不比任何运算符高,即进行运算,知道遇到括号或栈空
{
while (!a.empty())
{
if (a.top() == '(' || a.top() == ')')
break;
else
{
calulate(a.top());
a.pop();
}
}
}
else
{
while (!a.empty())//*和/只处理+和-,同上
{
if (a.top() == '(' || a.top() == ')')
break;
if (a.top() == '*' || a.top() == '/')
{
calulate(a.top());
a.pop();
}
else
{
break;
}
}
}
a.push(s[i]);
}
}
}
}
}
while (!a.empty())//栈中剩余的运算符,也要进行运算
{
calulate(a.top());
a.pop();
}
cout << "="<< b.top() << endl;
}
}