首页 > 代码库 > 表达式求值 (栈) 用C++实现

表达式求值 (栈) 用C++实现

  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 }    

 

表达式求值 (栈) 用C++实现