表達式求值是實現程序設計語言的基本問題之一,也是棧的應用的一個典型例子。設計一個程序,演示用算符優先法對算術表達式求值的過程
(1)從鍵盤輸入任意一個語法正確的(中綴)表達式,顯示並保存該表達式。
(2)利用棧結構,把上述(中綴)表達式轉換成后綴表達式,並顯示棧的狀態變化過程和所得到的后綴表達式。
(3)利用棧結構,對上述后綴表達式進行求值,並顯示棧的狀態變化過程和最終結果。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #define N 100 #define M 10 char suffix[N]; //后綴表達式 char ret[2]; //字符串棧進行彈出時的返回值(彈出元素) char tokens[N][M]; //令牌,將中綴表達式分解后的字符串數組 char ctokens[N][M]; //令牌,將后綴表達式分解后的字符串數組 int count; //tokens令牌的個數 int value; //表達式的值 int l = 0; //ctokens令牌的個數 typedef struct stack1{ //操作符棧 int top; char elem[N][2]; }stacki; typedef struct stack2{ //操作數棧 int top; int elem[N]; }stackj; typedef stacki* STACK; //指向操作符棧的指針 typedef stackj* DSTACK; //指向操作數棧的指針 void toSuffix(char *str); //將中綴表達式轉化成后綴表達式 int PreParse(char tokens[][M],char *str); //將中綴表達式分解成令牌返回令牌中字符串個數 int GetProsity(char *ch); //獲得操作符的優先級並返回 void push(STACK S,char *opt); //操作符棧的入棧 char *pop(STACK S); //操作符棧的出棧,並返回出棧元素 int IsEmpty(STACK S); //判斷操作符棧是否為空 void MakeNull(STACK S); //將操作符棧制空 void PrintStack(STACK S); //打印操作符棧 void dpush(DSTACK S,int opd); //操作符數的入棧 void dpop(DSTACK S); //操作符數的出棧 void PrintStack1(DSTACK S); //打印操作數棧 void MakeNull1(DSTACK S); //將操作數棧制空 int Evalute(char ctokens[][M]); //計算后綴表達式的值並返回 int main() { char str[N]; printf("Please input a expression:\n"); gets(str); //輸入所求中綴表達式str toSuffix(str); //將中綴表達式轉化成后綴表達式 puts(suffix); //輸出轉化后的后綴表達式 value = Evalute(ctokens); //計算后綴表達式的值 printf("%d",value); return 0; } void toSuffix(char *str) { int i; stacki stacks; //定義一個操作符棧stacks STACK optstack = &stacks; //定義操作符棧指針optstack MakeNull(optstack); count = PreParse(tokens,str); for(i = 0;i < count;i++) { if(!(strcmp(tokens[i],"+") && strcmp(tokens[i],"-") && strcmp(tokens[i],"*") && strcmp(tokens[i],"/") && strcmp(tokens[i],"(") && strcmp(tokens[i],")"))) { if(IsEmpty(optstack)) { push(optstack,tokens[i]); PrintStack(optstack); } else { if(!strcmp(tokens[i],"(")) { push(optstack,tokens[i]); PrintStack(optstack); } else if(!strcmp(tokens[i],")")) { while(strcmp(optstack->elem[optstack->top],"(")) //循環直到遇見左括號 { strcpy(ctokens[l],optstack->elem[optstack->top]); l++; strcat(suffix,pop(optstack)); PrintStack(optstack); } pop(optstack); //左括號彈出 PrintStack(optstack); } else { if(GetProsity(tokens[i]) > GetProsity(optstack->elem[optstack->top])) { push(optstack,tokens[i]); PrintStack(optstack); } else { while(optstack->top < 100) { if(GetProsity(tokens[i]) <= GetProsity(optstack->elem[optstack->top])) { strcpy(ctokens[l],optstack->elem[optstack->top]); l++; strcat(suffix,pop(optstack)); PrintStack(optstack); } else { break; } } push(optstack,tokens[i]); PrintStack(optstack); } } } } else //是數字則直接加到suffix的后面 { strcpy(ctokens[l],tokens[i]); l++; strcat(suffix,tokens[i]); } } while(optstack->top < 100) //將剩余元素彈出 { strcpy(ctokens[l],optstack->elem[optstack->top]); l++; strcat(suffix,pop(optstack)); } PrintStack(optstack); } int PreParse(char tokens[][M],char *str) { char p[N]; char temp[2]; int i=0,j = 0,l,k = 0; for(i = 0;i < strlen(str);i++) //刪除表達式中的空格 { if(str[i] == ' ') continue; else { p[j] = str[i]; j++; } } p[j] = '\0'; i = 0; for(j = 0;j < strlen(p);j++) { if(p[j] == '+' || p[j] == '-' || p[j] == '*' || p[j] == '/' || p[j] == '(' || p[j] == ')') //運算符轉化為字符串 { temp[0] = p[j]; temp[1] = '\0'; strcpy(tokens[k],temp); } else { for(l = 0;isdigit(p[j]);l++) //得到多位數字的字符串 { tokens[k][l] = p[j]; j++; } tokens[k][l] = '\0'; j--; } k++; } return k ; } int GetProsity(char *ch) { int prosity; if(!(strcmp(ch,"("))) { prosity = 0; } if(!(strcmp(ch,"+") && strcmp(ch,"-"))) { prosity = 1; } if(!(strcmp(ch,"*") && strcmp(ch,"/"))) { prosity = 2; } return prosity; } void push(STACK S,char *opt) { if(S->top == 0) { return ; } S->top--; strcpy(S->elem[S->top],opt); return ; } char *pop(STACK S) { strcpy(ret,S->elem[S->top]); S->top++; return ret; } int IsEmpty(STACK S) { if(S->top > N - 1) return 1; else return 0; } void MakeNull(STACK S) { S->top = N ; } void MakeNull1(DSTACK S) { S->top = N ; } void PrintStack(STACK S) { int i; for(i = N-1;i >= S->top;i--) { printf("%s",S->elem[i]); } printf("\n"); } void dpush(DSTACK S,int opd) { if(S->top == 0) { return ; } S->top--; S->elem[S->top] = opd; } void dpop(DSTACK S) { S->top++; } void PrintStack1(DSTACK S) { int i; for(i = N-1;i >= S->top;i--) { printf("%d ",S->elem[i]); } printf("\n"); } int Evalute(char ctokens[][M]) { int i; int ropd,lopd; int t; stackj stack; //定義一個操作數棧 DSTACK opdstack = &stack; //初始化操作數棧指針 MakeNull1(opdstack); for(i = 0;i < l;i++) { if(!strcmp(ctokens[i],"+")) //操作符則彈出兩棧內元素進行相應運算 { ropd = opdstack->elem[opdstack->top]; dpop(opdstack); lopd = opdstack->elem[opdstack->top]; dpop(opdstack); t = lopd + ropd; dpush(opdstack,t); PrintStack1(opdstack); } else if(!strcmp(ctokens[i],"-")) { ropd = opdstack->elem[opdstack->top]; dpop(opdstack); lopd = opdstack->elem[opdstack->top]; dpop(opdstack); t = lopd - ropd; dpush(opdstack,t); PrintStack1(opdstack); } else if(!strcmp(ctokens[i],"*")) { ropd = opdstack->elem[opdstack->top]; dpop(opdstack); lopd = opdstack->elem[opdstack->top]; dpop(opdstack); t = lopd * ropd; dpush(opdstack,t); PrintStack1(opdstack); } else if(!strcmp(ctokens[i],"/")) { ropd = opdstack->elem[opdstack->top]; dpop(opdstack); lopd = opdstack->elem[opdstack->top]; dpop(opdstack); t = lopd / ropd; dpush(opdstack,t); PrintStack1(opdstack); } else //操作數入棧 { dpush(opdstack,atoi(ctokens[i])); PrintStack1(opdstack); } } value = opdstack->elem[opdstack->top]; return value; }