nyoj 35-表达式求值(stack, 栈的应用)
35-表达式求值
内存限制:64MB
时间限制:3000ms
Special Judge: No
accepted:37
submit:53
题目描述:
ACM队的mdd想做一个计算器,但是,他要做的不仅仅是一计算一个A+B的计算器,他想实现随便输入一个表达式都能求出它的值的计算器,现在请你帮助他来实现这个计算器吧。
比如输入:“1+2/4=”,程序就输出1.50(结果保留两位小数)
比如输入:“1+2/4=”,程序就输出1.50(结果保留两位小数)
输入描述:
第一行输入一个整数n,共有n组测试数据(n<10)。 每组测试数据只有一行,是一个长度不超过1000的字符串,表示这个运算式,每个运算式都是以“=”结束。这个表达式里只包含+-*/与小括号这几种符号。其中小括号可以嵌套使用。数据保证输入的操作数中不会出现负数。 数据保证除数不会为0
输出描述:
每组都输出该组运算式的运算结果,输出结果保留两位小数。
样例输入:
2 1.000+2/4= ((1+2)*5+1)/4=
样例输出:
1.50 4.00
分析与步骤:
①、类似于表达式求解问题需要用到栈(stack)的思想(即就是先进后出)
②、遇到数字就将数字放入数字栈中
③、遇到字符串就要分开考虑
1、是‘(’就直接入栈,方便遇到')'时,就将'('以后所有的运算栈带入数字栈运算,结果保存于数字串
2、如果操作栈为空栈直接入栈
3、如果操作栈的栈顶元素优先级小于带输入字符的优先级直接入栈
4、其他情况就是要将数字栈与操作栈结合,算出结果保存在数字栈中
5、数字栈中的最后一个元素即为题解
核心代码(表达式求值模板);
1 int priority(char c) // 表达优先级的大小关系 2 { 3 if (c == '*' || c == '/') return 2; 4 if (c == '+' || c == '-') return 1; 5 return 0; 6 } 7 8 void cal(stack<char> &my_op, stack<double> &my_num) // 将数字栈与操作栈通过引用的形式实现调用与更改 9 { 10 double b = my_num.top(); 11 my_num.pop(); 12 double a = my_num.top(); 13 my_num.pop(); 14 switch(my_op.top()) 15 { 16 case '+': my_num.push(a + b); break; 17 case '-': my_num.push(a - b); break; 18 case '*': my_num.push(a * b); break; 19 case '/': my_num.push(a / b); break; 20 } 21 my_op.pop(); 22 } 23 for(int i = 0; i < len; ++ i) // 判断是因该执行什么操作 24 { 25 if(isdigit(s[i])) 26 { 27 double temp = atof(&s[i]); 28 while(isdigit(s[i]) || s[i] == '.') ++ i; 29 my_num.push(temp); 30 -- i; 31 } 32 else if(s[i] == '(') 33 { 34 my_op.push(s[i]); 35 } 36 else if(s[i] == ')') 37 { 38 while(my_op.top() != '(') 39 cal(my_op, my_num); 40 my_op.pop(); 41 } 42 else if(my_op.empty()) 43 { 44 my_op.push(s[i]); 45 } 46 else if(priority(my_op.top()) < priority(s[i])) 47 { 48 my_op.push(s[i]); 49 } 50 else if(priority(my_op.top()) >= priority(s[i])) 51 { 52 while(!my_op.empty() && priority(my_op.top()) >= priority(s[i])) // 比较的是优先级关系不是ASCⅡ 53 cal(my_op, my_num); 54 my_op.push(s[i]); 55 } 56 }
C/C++代码实现(AC):
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <cstdio> 5 #include <cmath> 6 #include <stack> 7 #include <map> 8 #include <queue> 9 #include <set> 10 11 using namespace std; 12 const int MAXN = 1010; 13 14 int priority(char c) // 表达优先级的大小关系 15 { 16 if (c == '*' || c == '/') return 2; 17 if (c == '+' || c == '-') return 1; 18 return 0; 19 } 20 21 void cal(stack<char> &my_op, stack<double> &my_num) // 将数字栈与操作栈通过引用的形式实现调用与更改 22 { 23 double b = my_num.top(); 24 my_num.pop(); 25 double a = my_num.top(); 26 my_num.pop(); 27 switch(my_op.top()) 28 { 29 case '+': 30 my_num.push(a + b); 31 break; 32 case '-': 33 my_num.push(a - b); 34 break; 35 case '*': 36 my_num.push(a * b); 37 break; 38 case '/': 39 my_num.push(a / b); 40 break; 41 } 42 my_op.pop(); 43 } 44 45 int main() 46 { 47 48 int t; 49 scanf("%d", &t); 50 while(t --) 51 { 52 char s[MAXN]; 53 scanf("%s", s); 54 int len = strlen(s); 55 stack <double> my_num; 56 stack <char> my_op; 57 58 for(int i = 0; i < len; ++ i) 59 { 60 if(isdigit(s[i])) 61 { 62 double temp = atof(&s[i]); 63 while(isdigit(s[i]) || s[i] == '.') ++ i; 64 my_num.push(temp); 65 -- i; 66 } 67 else if(s[i] == '(') 68 { 69 my_op.push(s[i]); 70 } 71 else if(s[i] == ')') 72 { 73 while(my_op.top() != '(') 74 cal(my_op, my_num); 75 my_op.pop(); 76 } 77 else if(my_op.empty()) 78 { 79 my_op.push(s[i]); 80 } 81 else if(priority(my_op.top()) < priority(s[i])) 82 { 83 my_op.push(s[i]); 84 } 85 else if(priority(my_op.top()) >= priority(s[i])) 86 { 87 while(!my_op.empty() && priority(my_op.top()) >= priority(s[i])) // 比较的是优先级关系不是ASCⅡ,my_op.top()忘记放在priority中,弄的找了半天的bug,::>_<:: 88 cal(my_op, my_num); 89 my_op.push(s[i]); 90 } 91 } 92 my_op.pop(); 93 printf("%.2lf\n", my_num.top()); 94 my_num.pop(); 95 } 96 return 0; 97 }