表达式计算(双栈实现)

复制代码
问题:计算下列表达式
  1+2*3-4-(2-(-1))*2+4/2
计算中包含+,-,*,/,(,),数字,负号(-)


1
#include <iostream> 2 #include <stack> 3 4 using namespace std; 5 6 bool isOp(string &val, int pos) { 7 if (val[pos] == '-') { 8 if (pos == 0 || (isOp(val, pos-1) && val[pos-1] != ')')) { 9 return false; 10 } 11 } 12 char c = val[pos]; 13 return (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')'); 14 } 15 16 int getPriority(char c) { 17 if (c == '(' || c == ')') 18 return 0; 19 else if (c == '+' || c == '-') 20 return 1; 21 else if (c == '*' || c == '/') 22 return 2; 23 return 0; 24 } 25 26 int getResult(int a, int b, char op) { 27 if (op == '+') 28 return a + b; 29 else if (op == '-') 30 return a - b; 31 else if (op == '*') 32 return a * b; 33 else if (op == '/') 34 return a / b; 35 return 0; 36 } 37 38 void calculate(stack<int> &data, stack<char> &op) { 39 char ch = op.top(); 40 int behind = data.top(); 41 data.pop(); 42 int before = data.top(); 43 data.pop(); 44 data.push(getResult(before, behind, ch)); 45 op.pop(); 46 } 47 48 int main() { 49 string val; 50 cin >> val; 51 int result = 0; 52 stack<int> data; 53 stack<char> op; 54 string tmp = ""; 55 for (int i = 0; i < val.length(); ++i) { 56 if (isOp(val, i) ) { 57 if (!tmp.empty()) { 58 data.push(atoi(tmp.c_str())); 59 tmp.clear(); 60 } 61 if (op.empty() || val[i] == '(') { 62 op.push(val[i]); 63 } else { 64 bool bKuoHao = false; 65 while (!op.empty() && getPriority(op.top()) >= getPriority(val[i])) { 66 if (val[i] == ')') { 67 while(!op.empty() && op.top() != '(') { 68 calculate(data, op); 69 } 70 op.pop(); 71 bKuoHao = true; 72 break; 73 } else { 74 calculate(data, op); 75 } 76 } 77 if (!bKuoHao) 78 op.push(val[i]); 79 } 80 } else { 81 tmp += val[i]; 82 if (i == val.length() - 1) { 83 data.push(atoi(tmp.c_str())); 84 tmp.clear(); 85 } 86 } 87 } 88 while(!op.empty()) { 89 calculate(data, op); 90 } 91 cout << data.top() << endl; 92 93 return 0; 94 }
复制代码

 

上面的不支持浮点数的计算,所以这里再调整一下数据类型,支持double

可计算浮点数 3.8*2.4-(2.3/1.2)

 

复制代码
 1 #include <iostream>
 2 #include <stack>
 3 
 4 using namespace std;
 5 
 6 //判断是否是运算符
 7 bool isOp(string &val, int pos) {
 8     if (val[pos] == '-') {
 9         if (pos == 0 || (isOp(val, pos-1) && val[pos-1] != ')')) { // 判断是负号就不能当成是运算符,直接写到数字里面
10             return false;
11         }
12     }
13     char c = val[pos];
14     return (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')');
15 }
16 
17 //计算符号的优先级
18 int getPriority(char c) {
19     if (c == '(' || c == ')')
20         return 0;
21     else if (c == '+' || c == '-') 
22         return 1;   
23     else if (c == '*' || c == '/')
24         return 2;
25     return 0;
26 }
27 
28 //计算函数,通过运算符实行对应的计算
29 double getResult(double a, double b, char op) {
30     if (op == '+')
31         return a + b;
32     else if (op == '-')
33         return a - b;
34     else if (op == '*')
35         return a * b;
36     else if (op == '/')
37         return a / b;
38     return 0;
39 }
40 
41 //操作栈计算栈顶的结果并放回栈中
42 void calculate(stack<double> &data, stack<char> &op) {
43     char ch = op.top();
44     double behind = data.top();
45     data.pop();
46     double before = data.top();
47     data.pop();
48     data.push(getResult(before, behind, ch));
49     op.pop();
50 }
51 
52 int main() {
53     string val;
54     while(cin >> val) {
55         stack<double> data;
56         stack<char> op;
57         string tmp = "";
58         for (int i = 0; i < val.length(); ++i) {
59             if (isOp(val, i) ) { // 如果当前位置表示的是运算符
60                 if (!tmp.empty()) { // 如果数字非空,则将数字压到数字栈中
61                     data.push(atof(tmp.c_str()));
62                     tmp.clear();
63                 }
64                 if (op.empty() || val[i] == '(') { // 符号栈空的情况下或者碰到左括号,直接压栈即可
65                     op.push(val[i]);
66                 } else {
67                     bool bKuoHao = false;
68                     while (!op.empty() && getPriority(op.top()) >= getPriority(val[i])) { // 当符号栈顶的优先级大于等于当前符号的优先级的时候,则需要先计算栈里面的值
69                         if (val[i] == ')') { // 如果当前的符号是右括号,需要特殊处理,计算栈直到遇到左括号结束
70                             while(!op.empty() && op.top() != '(') {
71                                 calculate(data, op);
72                             }
73                             op.pop();
74                             bKuoHao = true;
75                             break;
76                         } else { // 否则就是对栈顶的运算符进行计算
77                             calculate(data, op);
78                         }
79                     }
80                     if (!bKuoHao) // 括号的情况下不需要压栈
81                         op.push(val[i]);
82                 }
83             } else { //非运算符及累加起来转换成数字
84                 tmp += val[i];
85                 if (i == val.length() - 1) { // 最后一个数字需要特殊处理主动压栈
86                     data.push(atof(tmp.c_str()));
87                     tmp.clear();
88                 }
89             }
90         }
91         while(!op.empty()) {
92             calculate(data, op);
93         }
94         cout << data.top() << endl;
95     }
96     return 0;
97 }
复制代码

 

 

 

 

  

posted @   #忘乎所以#  阅读(46)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
历史上的今天:
2019-06-24 1033 To Fill or Not to Fill (25 分)
2019-06-24 1032 Sharing (25 分)
2019-06-24 1031 Hello World for U (20 分)
2019-06-24 1030 Travel Plan (30 分)
点击右上角即可分享
微信分享提示