用棧實現的計算器最終版本(可以實現括號以及浮點數的運算)
阿新 • • 發佈:2018-11-25
1 #include <stdio.h> 2 #include <ctype.h> 3 #include <stdlib.h> 4 5 #define STACK_INIT_SIZE 20 6 #define STACKINCREMENT 10 7 #define MAXBUFFER 10 8 9 typedef double ElemType; 10 typedef struct OPTR_SqStack { 11 char *base; 12 char *top; 13 int stackSize;14 } OPTR_SqStack; 15 16 typedef struct OPND_SqStack { 17 ElemType *base; 18 ElemType *top; 19 int stackSize; 20 } OPND_SqStack; 21 22 void Init_OPTR_Stack(OPTR_SqStack *S) { 23 S->base = (char *)malloc(STACK_INIT_SIZE * sizeof(char)); 24 if(!S->base) { 25 printf("Memory allocate failed!\n"); 26 exit(EXIT_FAILURE); 27 } 28 S->top = S->base; 29 S->stackSize = STACK_INIT_SIZE; 30 31 printf("棧初始化成功!\n"); 32 } 33 34 void Init_OPND_Stack(OPND_SqStack *S) { 35 S->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));36 if(!S->base) { 37 printf("Memory allocate failed!\n"); 38 exit(EXIT_FAILURE); 39 } 40 S->top = S->base; 41 S->stackSize = STACK_INIT_SIZE; 42 43 printf("棧初始化成功!\n"); 44 } 45 46 /*將資料元素壓棧*/ 47 void Push_OPTR(OPTR_SqStack *S, char data) { 48 if(S->top - S->base > S->stackSize) { 49 S->base = (char *)realloc(S->base, (S->stackSize + STACKINCREMENT) * sizeof(char)); 50 if(!S->base) { 51 printf("Memory allocate failed!\n"); 52 exit(EXIT_FAILURE); 53 } 54 S->top = S->base + S->stackSize; 55 S->stackSize += STACKINCREMENT; 56 } 57 /*資料元素入棧*/ 58 *S->top++ = data; 59 printf("操作符\'%c\'入棧成功!\n", data); 60 61 } 62 63 /*元素出棧*/ 64 void Pop_OPTR(OPTR_SqStack *S, char *data) { 65 if(S->base == S->top) { 66 printf("Error: Stack is NULL!\n"); 67 } 68 *data = *--S->top; 69 printf("操作符\'%c\'成功出棧!\n", *data); 70 } 71 72 void Push_OPND(OPND_SqStack *S, ElemType data) { 73 if(S->top - S->base > S->stackSize) { 74 S->base = (ElemType *)realloc(S->base, (S->stackSize + STACKINCREMENT) * sizeof(ElemType)); 75 if(!S->base) { 76 printf("Memory allocate failed!\n"); 77 exit(EXIT_FAILURE); 78 } 79 S->top = S->base + S->stackSize; 80 S->stackSize += STACKINCREMENT; 81 } 82 /*資料元素入棧*/ 83 *S->top++ = data; 84 printf("運算元\'%lf\'入棧成功!\n", data); 85 86 } 87 88 /*元素出棧*/ 89 void Pop_OPND(OPND_SqStack *S, ElemType *data) { 90 if(S->base == S->top) { 91 printf("Error: Stack is NULL!\n"); 92 } 93 *data = *--S->top; 94 } 95 96 /*取到棧頂的元素*/ 97 void GetTop_OPTR(OPTR_SqStack OPTR, char *data) { 98 if(OPTR.top == OPTR.base) { 99 printf("Stack is NULL!\n"); 100 exit(EXIT_FAILURE); 101 } 102 *data = *(OPTR.top - 1); 103 } 104 105 int isEmpty(OPTR_SqStack S) { 106 char theta; 107 108 GetTop_OPTR(S, &theta); 109 if(S.base == S.top || theta == '#') 110 return 1; 111 return 0; 112 } 113 114 void GetTop_OPND(OPND_SqStack OPND, ElemType *data) { 115 if(OPND.top == OPND.base) { 116 printf("Stack is NULL!\n"); 117 exit(EXIT_FAILURE); 118 } 119 *data = *(OPND.top - 1); 120 } 121 122 int InOP(char opdata) { 123 switch(opdata) { 124 case '+': 125 case '-': 126 case '*': 127 case '/': 128 case '(': 129 case ')': 130 case '#': 131 return 1; 132 default: 133 return 0; 134 } 135 } 136 137 int getIndex(char theta) { //獲取theta所對應的索引 138 int index = 0; 139 switch(theta) { 140 case '+': 141 index = 0; 142 break; 143 case '-': 144 index = 1; 145 break; 146 case '*': 147 index = 2; 148 break; 149 case '/': 150 index = 3; 151 break; 152 case '(': 153 index = 4; 154 break; 155 case ')': 156 index = 5; 157 break; 158 case '#': 159 index = 6; 160 default: 161 break; 162 } 163 return index; 164 } 165 166 char getPriority(char theta1, char theta2) { //獲取theta1與theta2之間的優先順序 167 const char priority[][7] = { //算符間的優先順序關係 168 /* + - * / ( ) \n*/ 169 { '>', '>', '<', '<', '<', '>', '>' }, /* + */ 170 { '>', '>', '<', '<', '<', '>', '>' }, /* - */ 171 { '>', '>', '>', '>', '<', '>', '>' }, /* * */ 172 { '>', '>', '>', '>', '<', '>', '>' }, /* / */ 173 { '<', '<', '<', '<', '<', '=', '0' }, /* ( */ 174 { '>', '>', '>', '>', '0', '>', '>' }, /* ) */ 175 { '<', '<', '<', '<', '<', '0', '=' }, /* \n */ 176 }; 177 178 int index1 = getIndex(theta1); 179 int index2 = getIndex(theta2); 180 return priority[index1][index2]; 181 } 182 183 int Operate(ElemType operand1, char theta, ElemType operand2) { 184 printf("進入開始計算的函數了!\n"); 185 printf("開始計算:%lf %c %lf...\n", operand1, theta, operand2); 186 switch(theta) { 187 case '+': 188 return operand1 + operand2; 189 case '-': 190 return operand1 - operand2; 191 case '*': 192 return operand1 * operand2; 193 case '/': 194 if(operand2 != 0) 195 return operand1 / operand2; 196 else { 197 printf("除數不能為0!\n"); 198 exit(EXIT_FAILURE); 199 } 200 } 201 printf("錯誤的操作符:\'%c\'!\n", theta); 202 exit(EXIT_FAILURE); 203 } 204 205 int isOperator(char opdata) { 206 switch(opdata) { 207 case '+': 208 case '-': 209 case '*': 210 case '/': 211 return 1; 212 default: 213 return 0; 214 } 215 } 216 217 int main() { 218 int i = 0; 219 ElemType result = 0; 220 char OPDATA[MAXBUFFER]; 221 char opdata;/*只用於輸入資料*/ 222 char theta;/*用於儲存輸入的字元*/ 223 ElemType operand1, operand2; 224 OPND_SqStack OPND; 225 OPTR_SqStack OPTR; 226 227 Init_OPTR_Stack(&OPTR); 228 Init_OPND_Stack(&OPND); 229 Push_OPTR(&OPTR, '#'); 230 231 /*如果輸入的不是換行符就表示繼續接收輸入*/ 232 printf("\n請輸入你想要計算的表示式: "); 233 while((opdata = getchar()) != '#') { 234 GetTop_OPTR(OPTR, &theta); 235 printf("\n此時取到的操作符棧頂元素為:\'%c\'\n", theta); 236 237 /*對運算元的操作*/ 238 printf("此時的輸入資料為:\'%c\'\n", opdata); 239 if(isdigit(opdata) || opdata == '.') { 240 OPDATA[i++] = opdata; 241 } 242 243 /*對運算子的處理if(InOP(opdata))*/ 244 else { 245 if(i != 0) { 246 OPDATA[i] = '\0'; 247 operand1 = atof(OPDATA); 248 Push_OPND(&OPND, operand1); 249 i = 0; 250 } 251 252 switch(getPriority(theta, opdata)) { //此處有問題 253 case '<': 254 /*如果當前的運算子的優先順序比前面的高,就入棧*/ 255 printf("\n當前操作符:\'%c\'優先順序比前一個\'%c\'高,入棧!\n", opdata, theta); 256 Push_OPTR(&OPTR, opdata); 257 break; 258 case '=': 259 case '0': 260 /*如果是#,或者括號,就出棧*/ 261 printf("\n當前操作符:\'%c\'優先順序與前一個\'%c\'相等,出棧!\n", opdata, theta); 262 Pop_OPTR(&OPTR, &theta); 263 break; 264 case '>': 265 /*如果當前操作符優先順序比前面的低,退棧並將運算結果入棧*/ 266 printf("\n當前操作符:\'%c\'優先順序比前一個\'%c\'低,開始計算!\n", opdata, theta); 267 Pop_OPTR(&OPTR, &theta); 268 printf("當前參與運算的操作符為:\'%c\'\n", theta); 269 printf("輸入的下一個資料為:%c\n", opdata); 270 271 if(theta == '(') 272 continue; 273 if(opdata == ')') { 274 while(theta != '(') { 275 Pop_OPND(&OPND, &operand2); 276 printf("運算元2:%lf\n", operand2); 277 Pop_OPND(&OPND, &operand1); 278 printf("運算元1:%lf\n", operand1); 279 Push_OPND(&OPND, Operate(operand1, theta, operand2)); 280 Pop_OPTR(&OPTR, &theta); 281 printf("下一個操作符為:\'%c\'\n", theta); 282 } 283 continue; 284 } 285 286 /*如果上述if不成立任然要執行的語句*/ 287 Pop_OPND(&OPND, &operand2); 288 printf("運算元2:%lf\n", operand2); 289 Pop_OPND(&OPND, &operand1); 290 printf("運算元1:%lf\n", operand1); 291 Push_OPND(&OPND, Operate(operand1, theta, operand2)); 292 293 /*如果當前輸入的資料為計算符就入棧*/ 294 if(isOperator(opdata)) { 295 Push_OPTR(&OPTR, opdata); 296 } 297 printf("\n===========現在開始下一次的計算了!===========\n"); 298 break; 299 } 300 } 301 } 302 303 if(i != 0) { 304 OPDATA[i] = '\0'; 305 operand1 = atoi(OPDATA); 306 Push_OPND(&OPND, operand1); 307 i = 0; 308 } 309 printf("\n==========表示式輸入結束了,現在開始計算了!==========\n"); 310 while(!isEmpty(OPTR)) { 311 Pop_OPTR(&OPTR, &theta); 312 printf("操作符為:\'%c\'\n", theta); 313 if(theta == '(') 314 continue; 315 Pop_OPND(&OPND, &operand2); 316 printf("運算元2:%lf\n", operand2); 317 Pop_OPND(&OPND, &operand1); 318 printf("運算元1:%lf\n", operand1); 319 Push_OPND(&OPND, Operate(operand1, theta, operand2)); 320 } 321 GetTop_OPND(OPND, &result); 322 printf("計算的結果為: %.2lf\n", result); 323 324 return 0; 325 } 326 /*2+(2+3)*5-(4+4)+1 327 2+5*5-(4+4)+1 328 2+25-(4+4)+1 329 27-(4+4)+1 330 27-8+1 331 19+1 332 20 333 20 334 (6+4/2)*5-6/3*4+7 335 40-8+7=39 336 */