(中序波兰式求解) 请编写程序求解中序波兰式的值。表达式中可能的运算符有+,-,*,/,()。
【输入】中序波兰式
【输出】波兰式的值 //输出的数据类型符合C/C++对表达式求值的定义,即表达式的输出类型由高精度的运算数来决定。
浮点型保留小数点后的3位小数
例如:
【输入】2*(4+5)-12
【输出】6
【输入】2*2.5
【输出】5.000
备注:
(1)对于80%的测试数据运算数中仅仅包含正整数;
(2)对于10%的测试数据运算数中包含有浮点数;
(3)对于10%的测试数据运算数中包含有负数;
话不多说,直接上代码。
#include <bits/stdc++.h>
using namespace std;
stack<int> num;
// 存储运算数
stack<double> fnum;
// 存储浮点运算数
stack<char> op;
// 存储运算符,记录优先级
unordered_map<char, int> cmp = {
{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}
};
void eval(void)
{
int b = num.top();
num.pop();
// 第二个数
int a = num.top();
num.pop();
// 第一个数
char opr = op.top();
op.pop();
// 运算符
int x;
if (opr == '+')
x = a + b;
else if (opr == '-')
x = a - b;
else if (opr == '*')
x = a * b;
else
x = a / b;
num.push(x);
}
void feval(void)
{
double b = fnum.top();
fnum.pop();
double a = fnum.top();
fnum.pop();
char opr = op.top();
op.pop();
double x;
if (opr == '+')
x = a + b;
else if (opr == '-')
x = a - b;
else if (opr == '*')
x = a * b;
else
x = a / b;
fnum.push(x);
}
int main()
{
string str;
cin >> str;
bool flag = true;
for (int i = 0; i < str.length(); i++)
{
if (str[i] == '.')
{
flag = false;
break;
}
}
//判断是否有浮点数存在
if (str[0] == '-')
{
num.push(-1);
fnum.push(-1);
str[0]='*';
}
//首位是否为负数
if (flag)
{
for (int i = 0; i < str.size(); i++)
{
char c = str[i];
// 读入运算数
if (isdigit(c))//是否为数字
{
int j = i, x = 0;
while (j < str.size() && isdigit(str[j]))
{
x = x * 10 + str[j++] - '0';
}
num.push(x);
i = j - 1;//更新
}
else if (c == '(')
{
// 标记括号内数据
op.push(c);
if(str[i+1]=='-') {num.push(-1); str[i+1]='*';}
//一开始漏判断中间继续出现类似于5-(-(1+2)/2)中后续再有前置-号的情况了 已更正
//遇到左括号直接入栈,遇到右括号计算括号里面的
}
else if (c == ')')
{
//先算括号
while (op.size() && op.top() != '(')
eval();
// 弹出(
op.pop();
}
else
{
// 得先算乘除再算加减
// 待入栈运算符优先级低,则先计算
while (op.size() && cmp[op.top()] >= cmp[c])
eval();
// 操作符入栈
op.push(c);
}
}
while (op.size())
eval(); // 剩余的进行计算
cout << num.top() << endl; // 输出结果
}
else//浮点型大同小异
{
for (int i = 0; i < str.size(); i++)
{
char c = str[i];
if (isdigit(c))
{
int j = i;
double x = 0;
while (j < str.size() && isdigit(str[j]))
{
x = x * 10 + str[j++] - '0';
}
double xx = 0;
if (str[j] == '.')
{
j++;
while (j < str.size() && isdigit(str[j]))
{
xx = xx * 10 + str[j++] - '0';
}
while (xx >= 1)
{
xx /= 10;
}
}//cout << xx << endl;
x += xx;
// cout << x << endl;
fnum.push(x);
i = j - 1;
}
else if (c == '(')
{
op.push(c);
if(str[i+1]=='-') {num.push(-1); str[i+1]='*';}
}
else if (c == ')')
{
while (op.size() && op.top() != '(')
feval();
op.pop();
}
else
{
while (op.size() && cmp[op.top()] >= cmp[c])
feval();
op.push(c);
}
}
while (op.size())
feval();
printf("%.3f\n", fnum.top());
}
return 0;
}