题目描述
读入一个只包含+,-,x,/,(,)的非负整数计算表达式,计算该表达式的值
输入格式
测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。
没有非法表达式。当一行中只有0时输入结束,相应的结果不要输出。
输出格式
对每个测试用例输出1行,即该表达式的值,精确到小数点后2位。
样例输入
30 / 90 - 26 + 97 - 5 - 6 - 13 / 88 * 6 + 51 / 29 + 79 * 87 + 57 * 92
0
样例输出
12178.21
解题思路:
使用两个栈来实现,将中缀表达式变为后缀表达式来求解
使用两个栈,一个为操作符栈,一个为操作数栈
使用map数据结构来存储操作符的优先级
需要注意的是,若当前的操作符的优先级小于等于操作符栈顶的优先级,则弹出两个操作数,并弹出一个操作符进行计算,然后将结果存入操作数栈。(此操作使用while循环进行)
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<stack>
#include<queue>
using namespace std;
map<char, int> m;//存储优先级
//计算 当前操作符的优先级小于等于栈中的操作符的优先级
//此方法为提取代码中冗余的代码片段,只需将其放入对应的执行处即可
void calHelper(stack<double> &nums,stack<char> &ops) {
double num2 = nums.top();//第二操作数
nums.pop();
double num1 = nums.top();//第一操作数
nums.pop();
char op = ops.top();//操作符
ops.pop();
double temp;
if (op == '+')
{
temp = num1 + num2;
}
else if (op == '-')
{
temp = num1 - num2;
}
else if (op == '*')
{
temp = num1 * num2;
}
else if (op == '/')
{
temp = num1 / num2;
}
nums.push(temp);
}
//求出表达式的值
double calculate(string str) {
stack<double> nums;//存放操作数
stack<char> ops;//存放表达式符号
for (int i = 0; i < str.size();)
{
if (str[i] >= '0' && str[i] <= '9') {//为操作数
int num = str[i++] - '0';
while (i < str.size() && str[i] >= '0' && str[i] <= '9' )//数字可能不止一位
{
num = num * 10 + (str[i] - '0');//更新操作数
i++;
}
nums.push(num);//将操作数压入操作数栈
}
else if(str[i] == '(')//左括号直接压入操作符栈
{
ops.push(str[i]);
i++;
}
else if(str[i] == ')')//处理右括号
{
while (!ops.empty() && ops.top() != '(' )
{
double num2 = nums.top();//第二操作数
nums.pop();
double num1 = nums.top();//第一操作数
nums.pop();
char op = ops.top();//操作符
ops.pop();
double temp;
if (op == '+')
{
temp = num1 + num2;
}
else if (op == '-')
{
temp = num1 - num2;
}
else if (op == '*')
{
temp = num1 * num2;
}
else if (op == '/')
{
temp = num1 / num2;
}
nums.push(temp);
}
ops.pop();
i++;
}
else//为操作符
{
while ( !ops.empty() && m.find(str[i])->second <= m.find(ops.top())->second )
{//当前操作符的优先级小于等于栈中的操作符的优先级
double num2 = nums.top();//第二操作数
nums.pop();
double num1 = nums.top();//第一操作数
nums.pop();
char op = ops.top();//操作符
ops.pop();
double temp;
if (op == '+')
{
temp = num1 + num2;
}
else if (op == '-')
{
temp = num1 - num2;
}
else if (op == '*')
{
temp = num1 * num2;
}
else if (op == '/')
{
temp = num1 / num2;
}
nums.push(temp);
}
ops.push(str[i]);//将操作符压入操作符栈
i++;
}
}
while (!ops.empty())
{//当前操作符的优先级小于等于栈中的操作符的优先级
double num2 = nums.top();//第二操作数
nums.pop();
double num1 = nums.top();//第一操作数
nums.pop();
char op = ops.top();//操作符
ops.pop();
double temp;
if (op == '+')
{
temp = num1 + num2;
}
else if (op == '-')
{
temp = num1 - num2;
}
else if (op == '*')
{
temp = num1 * num2;
}
else if (op == '/')
{
temp = num1 / num2;
}
nums.push(temp);
}
return nums.top();
}
int main() {
string str;
vector<string> v;//存储所求表达式
//数值越大,优先级越高
m.insert(pair<char, int>('+', 1));
m.insert(pair<char, int>('-', 1));
m.insert(pair<char, int>('*', 2));
m.insert(pair<char, int>('/', 2));
m.insert(pair<char, int>('(', 3));
m.insert(pair<char, int>(')', 3));
while (getline(cin,str),str !="0")
{
for (string::iterator it = str.begin(); it != str.end(); it++) {
if ((*it) == ' ') {
str.erase(it);
}
}
v.push_back(str);
}
for (vector<string>::iterator it = v.begin(); it != v.end(); it++) {
double result = calculate(*it);
printf_s("%.2f\n",result);
}
system("pause");
return 0;
}