算術表示式求值
阿新 • • 發佈:2018-12-10
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <conio.h> #include <ctype.h> #define OK 1 #define ERROR 0 #define STACK_INIT_SIZE 100 //#define STACKINCREMENT 10 //======================================================== // 以下定義兩種棧,分別存放運算子和數字 //======================================================== //*******************運算子棧部分************************* struct SqStack //定義棧 { char *base; //棧底指標 char *top; //棧頂指標 int stacksize; //棧的長度 }; int InitStack (SqStack &s) //建立一個空棧S { if (!(s.base = (char *)malloc(50 * sizeof(char)))) exit(0); s.top=s.base; s.stacksize=50; return OK; } char GetTop(SqStack s,char &e) //運算子取棧頂元素 { if (s.top==s.base) //棧為空的時候返回ERROR { printf("運算子棧為空!\n"); return ERROR; } else e=*(s.top-1); //棧不為空的時候用e做返回值,返回S的棧頂元素,並返回OK return OK; } int Push(SqStack &s,char e) //運算子入棧 { if (s.top-s.base >= s.stacksize) { printf("運算子棧滿!\n"); s.base=(char*)realloc (s.base,(s.stacksize+5)*sizeof(char) ); //棧滿的時候,追加5個儲存空間 if(!s.base) exit (OVERFLOW); s.top=s.base+s.stacksize; s.stacksize+=5; } *(s.top)++=e; //把e入棧 return OK; } int Pop(SqStack &s,char &e) //運算子出棧 { if (s.top==s.base) //棧為空棧的時候,返回ERROR { printf("運算子棧為空!\n"); return ERROR; } else { e=*--s.top; //棧不為空的時候用e做返回值,刪除S的棧頂元素,並返回OK return OK; } } int StackTraverse(SqStack &s) //運算子棧的遍歷 { char *t; t=s.base ; if (s.top==s.base) { printf("運算子棧為空!\n"); //棧為空棧的時候返回ERROR return ERROR; } while(t!=s.top) { printf(" %c",*t); //棧不為空的時候依次取出棧內元素 t++; } return ERROR; } //**********************數字棧部分*************************** struct SqStackn //定義數棧 { int *base; //棧底指標 int *top; //棧頂指標 int stacksize; //棧的長度 }; int InitStackn (SqStackn &s) //建立一個空棧S { s.base=(int*)malloc(50*sizeof(int)); if(!s.base)exit(OVERFLOW); //儲存分配失敗 s.top=s.base; s.stacksize=50; return OK; } int GetTopn(SqStackn s,int &e) //數棧取棧頂元素 { if (s.top==s.base) { printf("運算數棧為空!\n"); //棧為空的時候返回ERROR return ERROR; } else e=*(s.top-1); //棧不為空的時候,用e作返回值,返回S的棧頂元素,並返回OK return OK; } int Pushn(SqStackn &s,int e) //數棧入棧 { if (s.top-s.base >=s.stacksize) { printf("運算數棧滿!\n"); //棧滿的時候,追加5個儲存空間 s.base=(int*)realloc (s.base,(s.stacksize+5)*sizeof(int) ); if(!s.base) exit (OVERFLOW); s.top=s.base+s.stacksize; //插入元素e為新的棧頂元素 s.stacksize+=5; } *(s.top)++=e; //棧頂指標變化 return OK; } int Popn(SqStackn &s,int &e) //數棧出棧 { if (s.top==s.base) { printf(" 運算子棧為空!\n"); //棧為空棧的視時候,返回ERROR return ERROR; } else { e=*--s.top; //棧不空的時候,則刪除S的棧頂元素,用e返回其值,並返回OK return OK; } } int StackTraversen(SqStackn &s) //數棧遍歷 { int *t; t=s.base ; if (s.top==s.base) { printf(" 運算數棧為空!\n"); //棧為空棧的時候返回ERROR return ERROR; } while(t!=s.top) { printf(" %d",*t); //棧不為空的時候依次輸出 t++; } return ERROR; } //======================================================== // 以下定義函式 //======================================================== int Isoperator(char ch) //判斷是否為運算子,分別將運算子和數字進入不同的棧 { switch (ch) { case '+': case '-': case '*': case '/': case '(': case ')': case '#': return 1; default: return 0; } } int Operate(int a, char op, int b) //運算操作 { int result; switch(op) { case '+': result=a+b; break; case '-': result=a-b; break; case '*': result=a*b; break; case '/': result=a/b; break; } return result; } char Precede(char ch1, char ch2) //運算子優先順序的比較 { char p; switch(ch1) { case '+': case '-': if (ch2=='+'||ch2=='-'||ch2==')'||ch2=='#') p = '>'; //ch1運算子的優先順序小於ch2運算子 else p = '<'; break; case '*': case '/': if (ch2 == '(') p = '<'; else p = '>'; break; case '(': if (ch2 == ')') p = '='; else if (ch2 == '#') { printf(" 表示式錯誤!運算子不匹配!\n") ; exit(0); } else p = '<'; break ; case ')': if (ch2 == '(') { printf(" 表示式錯誤!運算子不匹配!\n") ; exit(0); } else p = '>'; break ; case '#': if (ch2 == ')') { printf(" 表示式錯誤!運算子不匹配!\n") ; exit(0); } else if (ch2 == '#') p = '='; else p='<'; break; } return p; } //======================================================== // 以下是求值過程 //======================================================== int EvaluateExpression() //參考書p53演算法3.4 { int a, b, temp, answer; char ch,op,e; char *str; int j = 0; SqStackn OPND; //OPND為運算數字棧 SqStack OPTR; //OPTR為運算子棧 InitStack(OPTR); Push(OPTR,'#'); //,所以此棧底是'#',因為運算子棧以'#'作為結束標誌 InitStackn(OPND); // printf("\n\n按任意鍵開始求解:\n\n"); // ch=getch(); printf("\n請輸入表示式並以'#'結束:\n"); str =(char*)malloc(50*sizeof(char)); gets(str); ch=str[j]; //ch是字元型的,而e是整型的整數 j++; GetTop(OPTR,e); //e為棧頂元素返回值 while (ch!='#' || e!='#') { if (!Isoperator(ch)) //遇到數字,轉換成十進位制並計算 { temp=ch-'0'; //將字元轉換為十進位制數 ch=str[j]; j++; while(!Isoperator(ch)) { temp=temp*10 + ch-'0'; //將逐個讀入運算數的各位轉化為十進位制數 ch=str[j]; j++; } Pushn(OPND,temp); } else if (Isoperator(ch)) //判斷是否是運算子,不是運算子則進棧 switch (Precede(e,ch)) { case '<' : Push(OPTR,ch); // 棧頂元素優先權低 ch = str[j++]; printf("\n\n 運算子棧為:\n"); //輸出棧,顯示棧的變化 StackTraverse(OPTR); printf("\n 運算數棧為:\n"); StackTraversen(OPND); break; case '=' : Pop(OPTR,op); // 脫括號並接收下一字元 ch = str[j++] ; printf("\n\n 運算子棧為:\n"); StackTraverse(OPTR); printf("\n 數棧為:\n"); StackTraversen(OPND); break; case '>' : Pop(OPTR,op); //彈出最上面兩個,並運算,把結果進棧 Popn(OPND,b); Popn(OPND,a); Pushn(OPND,Operate(a,op,b)); printf("\n\n 運算子棧為:\n"); StackTraverse(OPTR); printf("\n 數棧為:\n"); StackTraversen(OPND); } else { printf("您的輸入有問題,請檢查重新輸入!"); exit(0); } GetTop(OPTR,e); //取出運算子棧最上面元素是否是'#' } //while GetTopn(OPND,answer); //已輸出。數字棧最上面即是最終結果 return answer; } //======================================================== // 執行部分 //======================================================== void ShowMenu() { printf("\n\n"); printf(" 表示式求值系統\n"); } void Quit(); void Manage() { int answer; // ShowMenu(); answer=EvaluateExpression(); printf("\n\n表示式結果是: %d\n",answer); Quit(); } void Quit() { char ch; printf(" 本次運算結束。\n"); printf(" 繼續本系統嗎?\n\n"); printf(" 繼續運算請按Y/y "); printf("\n 退出程式請按N/n "); printf(" \n___________________________________________________________________\n"); ch=getch(); ch=toupper(ch); //將ch字元轉換成大寫字母 if(ch == 'N') { printf("\n\n 系統退出。\n"); exit(0); } Manage(); } int main() { ShowMenu(); Manage(); return 0; }