题目描述:
假设表达式定义为: 1. 一个十进制的正整数 X 是一个表达式。 2. 如果 X 和 Y 是 表达式,则 X+Y, X*Y 也是表达式; *优先级高于+. 3. 如果 X 和 Y 是 表达式,则 函数 Smax(X,Y)也是表达式,其值为:先分别求出 X ,Y 值的各位数字之和,再从中选最大数。 4.如果 X 是 表达式,则 (X)也是表达式。 例如: 表达式 12*(2+3)+Smax(333,220+280) 的值为 69。 请你编程,对给定的表达式,输出其值。
输入描述:
【标准输入】 第一行: T 表示要计算的表达式个数 (1≤ T ≤ 10) 接下来有 T 行, 每行是一个字符串,表示待求的表达式,长度<=1000
输出描述:
【标准输出】 对于每个表达式,输出一行,表示对应表达式的值。
样例输入:
复制
3 12+2*3 12*(2+3) 12*(2+3)+Smax(333,220+280)
样例输出:
18 60 69
思路:
先看下面的链接 前缀、中缀、后缀 表达式及其求值,了解其思想
https://blog.csdn.net/antineutrino/article/details/6763722/
和普通的表达式求值比起来多了一种,Smax运算,这个运算的优先级和()相同
有了双栈的思想,模拟运算即可
只不过右括号有两种匹配方式,其中做点处理
详见代码
代码:
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<queue>
#include<stack>
#include<map>
using namespace std;
char s[1005];
map<char,int> mp;
stack<char> s2;//符号
stack<int> s1;//数字
int Smax(int a)
{
int b = 0;
while(a) b += a%10, a /= 10;
return b;
}
void solve(int li)
{
int a, b, c, d;
while(!s2.empty() && mp[s2.top()] < li)
{
if(s2.top() == ',')
{
c = s1.top();
s2.pop();
s1.pop();
continue;
}
a = s1.top(); s1.pop();
b = s1.top(); s1.pop();
if(s2.top() == '*') s1.push(a*b);
if(s2.top() == '+') s1.push(a+b);
s2.pop();
}
if(li == 2)
{
if(s2.top() == '<')
{
d = s1.top();
s1.pop();
a = Smax(c), b = Smax(d);
s1.push(a > b ? a : b);
}
s2.pop();
}
}
int main()
{
mp['*'] = 0;
mp['+'] = 0;
mp[','] = 1;
mp['<'] = 2;
mp['('] = 2;
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",s);
int len = strlen(s);
for(int i = 0; i < len; i++)
{
if(isdigit(s[i]))
{
int t = 0;
while(isdigit(s[i]))
{
t *= 10;
t += s[i] - '0';
i++;
}
i--;
s1.push(t);
}
else if(s[i] == ')') solve(2); //如果是右括号,处理到一个出现 '<' 或者 '('
else if(s[i] == '+') solve(1), s2.push('+'); //如果是+号,将栈顶的 * 和 + 处理干净
else if(s[i] == 'S') s2.push('<'), i += 4;
else s2.push(s[i]);//'(' ',' '*' 直接入栈
}
solve(10);//处理干净剩余的操作符
printf("%d\n",s1.top());
while(!s1.empty()) s1.pop();//其实不清空问题不大,但每做一次运算,内存消耗就会增加
}
return 0;
}