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 }