1 #include <cstdio>
2
3 #include <cstdlib>
4
5 #include <cmath>
6
7 #include <stack>
8
9 #include <cstring>
10
11 using namespace std;
12
13
14
15 char Precede(char a, char b) { //判断运算符优先级
16
17 int i, j;
18
19 char Table[8][8] = {
20
21 {' ','+','-','*','/','(',')','='},
22
23 {'+','>','>','<','<','<','>','>'},
24
25 {'-','>','>','<','<','<','>','>'},
26
27 {'*','>','>','>','>','<','>','>'},
28
29 {'/','>','>','>','>','<','>','>'},
30
31 {'(','<','<','<','<','<','=',' '},
32
33 {')','>','>','>','>',' ','>','>'},
34
35 {'=','<','<','<','<','<',' ','='}
36
37 }; //优先级表格
38
39 for(i=0; i<8; i++)
40
41 if(Table[0][i]==a) //寻找运算符a
42
43 break;
44
45 for(j=0; j<8; j++) //寻找运算符b
46
47 if(Table[j][0]==b)
48
49 break;
50
51 return Table[j][i];
52
53 }
54
55
56
57 bool Calcu_temp(double a, char theta, double b, double &r) { //计算二元表达式的值
58
59 if(theta=='+')
60
61 r = a + b;
62
63 else if(theta=='-')
64
65 r = a - b;
66
67 else if(theta=='*')
68
69 r = a * b;
70
71 else {
72
73 if(fabs(b-0.0)<1e-8) //如果除数为0,返回错误信息
74
75 return false;
76
77 else
78
79 r = a / b;
80
81 }
82
83 return true;
84
85 }
86
87
88
89 bool IsOper(char ch) { //判断字符ch是否为运算符
90
91 char ptr[10] = {'+', '-', '*', '/', '(', ')', '='};
92
93 int i;
94
95 for(i=0; i<7; i++) {
96
97 if(ch==ptr[i])
98
99 return true;
100
101 }
102
103 return false;
104
105 }
106
107
108
109 bool Calculate(char s[], double &result) { //计算表达式的结果
110
111 char theta;
112
113 int i = 0, j, point = 0;
114
115 double a, b, r, num = 0;
116
117 stack<double> num_stack; //数字栈
118
119 stack<char> oper_stack; //运算符栈
120
121 oper_stack.push('=');
122
123 while(s[i]!='=' || oper_stack.top()!='=') { //对表达式a进行计算
124
125 if((s[i]>='0' && s[i]<='9') || s[i]=='.') { //字符是数字或者小数点
126
127 num = 0; //初始化数字为0
128
129 point = 0; //point用来标记是否出现小数点以及当前处于小数点后第x位,point==10^x
130
131 if(s[i]=='.')
132
133 point = 10;
134
135 else
136
137 num = s[i] - 48;
138
139 j = i + 1;
140
141 while(!IsOper(s[j])) { //继续往后查找并记录该数字,直到该数字结束遇到运算符为止
142
143 if(s[j]=='.') {
144
145 point = 10;
146
147 j++;
148
149 continue;
150
151 }
152
153 if(!point) //整数部分
154
155 num = num * 10 + ( s[j] - 48 );
156
157 else {
158
159 num = num + 1.0 * ( s[j] - 48 ) / point; //小数部分
160
161 point *= 10; //小数位数后移一位
162
163 }
164
165 j++;
166
167 }
168
169 i = j;
170
171 num_stack.push(num); //将该数字压入栈中
172
173 }
174
175 else if(IsOper(s[i])) { //字符是运算符
176
177 switch(Precede(s[i],oper_stack.top())) { //该运算符和栈顶运算符进行优先级比较并做相关处理
178
179 case '<':
180
181 oper_stack.push(s[i++]);
182
183 break;
184
185 case '=':
186
187 oper_stack.pop();
188
189 i++;
190
191 break;
192
193 case '>':
194
195 theta = oper_stack.top(); //从栈中弹出一个运算符进行计算
196
197 oper_stack.pop();
198
199 b = num_stack.top(); //弹出两个数字,注意顺序,先弹出的数是第二个操作数
200
201 num_stack.pop();
202
203 a = num_stack.top();
204
205 num_stack.pop();
206
207 if ( Calcu_temp(a, theta, b, r) ) //计算并判断是否有除数等于0的情况
208
209 num_stack.push(r); //若正常,则将结果压入栈中
210
211 else
212
213 return false; //出现除数为0的情况,返回错误信息
214
215 break;
216
217 }
218
219 }
220
221 }
222
223 result = num_stack.top(); //最后数字栈中的数即为表达式的最终结果
224
225 return true;
226
227 }
228
229
230
231 bool Check(char s[]) { //检查表达式括号是否匹配
232
233 int flag=0, i;
234
235 for(i=0; s[i]!=0; i++) {
236
237 if(s[i]=='(')
238
239 flag++;
240
241 if(s[i]==')')
242
243 flag--;
244
245 }
246
247 if(flag)
248
249 return false;
250
251 else
252
253 return true;
254
255 }
256
257
258
259 int main() {
260
261 // freopen("in.txt", "r", stdin);
262
263 int i, j;
264
265 char s1[210], s2[210];
266
267 double result;
268 printf("\t\t表达式求值(栈)\n");
269 printf("******************************************************************\n");
270 printf("请输入表达式,等号不用输入:\n");
271
272 while(gets(s1)!=NULL) { //输入表达式
273
274 if(strlen(s1)==1 && s1[0]=='0')
275
276 break;
277
278 for(i=0,j=0; s1[i]!=0; i++) { //将表达式转换为规格化的表达式,并在末尾加上“=”,保存在s2中
279
280 if(s1[i]==' ')
281
282 continue;
283
284 s2[j++] = s1[i];
285
286 }
287
288 s2[j++] = '=';
289
290 s2[j] = '\0';
291
292 if(Check(s2)) { //检查括号是否匹配
293
294 if(Calculate(s2, result)) //计算并检查表达式中是否出现除数为0的情况
295
296 printf("%lf\n",result);
297
298 else
299
300 printf("除数不能为0\n");
301
302 }
303
304 else
305
306 printf("括号不匹配\n");
307
308 }
309
310 return 0;
311
312 }