資料結構——表示式求值(程式碼)
阿新 • • 發佈:2018-11-04
表示式求值
C++ 環境codeblocks17 通過
/* 表示式求值,可用運算子 +-/*(){}[] @CGQ 2018/10/30 */ #include<stdio.h> #include<stdlib.h> #include<ctype.h> #include<stack> char compare(char, char); //比較運算子優先順序 float Operation(float, float, float ); //實際運算函式 int getnext(float * n); //該函式返回0為數字,返回1為運算子 float EvaluateExpression(); //表示式求值返回結果 int getnext(float * n) //該函式返回0為數字,返回1為運算子 { char c; *n = 0; while((c = getchar()) == ' '); //跳過空格 if(!isdigit(c)) //判斷是否是數字 { // 不是數字 if(c=='{'||c=='[') *n = '('; else if(c=='}'||c==']') *n = ')'; else *n = c; return 1; } do { *n = *n * 10 + (c - '0'); //使用迴圈獲得連續的數字,乘10進位 c = getchar(); } while(isdigit(c)); ungetc(c, stdin); //讀到一個運算子,將運算子寫回輸入快取 return 0; } /* 對於連續出現的運算子進行比較優先順序 結果有> < =,可以得到+-×/之間的優 先級,加減乘除的優先順序都低於'(', 但是都高於')',並且根據從左到右運算 可知當運算子相同時,第一個大於第二 個,0表示不存在 */ char compare(char a, char b) { int i, j; char pre[7][7] = //定義運算子之間的優先順序 { {'>','>','<','<','<','>','>'}, {'>','>','<','<','<','>','>'}, {'>','>','>','>','<','>','>'}, {'>','>','>','>','<','>','>'}, {'<','<','<','<','<','=','0'}, {'>','>','>','>','0','>','>'}, {'<','<','<','<','<','0','='}, }; switch(a) { case '+': i = 0; break; case '-': i = 1; break; case '*': i = 2; break; case '/': i = 3; break; case '(': i = 4; break; case ')': i = 5; break; case '#': i = 6; break; } switch(b) { case '+': j = 0; break; case '-': j = 1; break; case '*': j = 2; break; case '/': j = 3; break; case '(': j = 4; break; case ')': j = 5; break; case '#': j = 6; break; default: printf("表示式要以#結尾!!!\n"); exit(1); } return pre[i][j]; } float Operation(float a, float operate, float b) //實際操作兩個數a,b的運算 { float result; a = (float)a; b = (float)b; switch((int)operate) { case '+': result = a + b; break; case '-': result = a - b; break; case '*': result = a * b; break; case '/': result = a / b; break; } return result; } float EvaluateExpression() { float c; //儲存輸入快取中的字元或數字 float flag; //從輸入快取中取操作符的返回值,0表示取出數字,1表示取出運算子 float x; //取棧頂操作符 char operate; //儲存要計算的操作符 float a, b; //存取要計算的運算元 std::stack<float> ns; std::stack<char> os; //ns為運算元棧,os為運算子棧 os.push('#'); flag = getnext(&c); x = os.top(); while((float)c != '#' || (float)x != '#') //表示式的起始位置都是'#',如果讀取的新的字元和運算子都是'#'說明運算已經結束 { if(flag == 0) //返回數字 { ns.push(c); flag = getnext(&c); } else //返回運算子 { x = os.top(); //取棧頂運算子 switch(compare((float)x, (float)c)) { case '<': //棧頂操作符運算優先順序低 os.push(c); flag = getnext(&c); break; case '>': //棧頂運算子優先順序高,先退出兩個資料進行運算,然後將運算結果在存入資料棧 operate = os.top(); os.pop(); a = ns.top(); ns.pop(); b = ns.top(); ns.pop(); ns.push(Operation(b, operate, a)); //由於壓棧的順序,則應當是先出的運算元在後 break; case '=': //操作符'('')'緊挨,則直接去除括號 operate = os.top(); os.pop(); flag = getnext(&c); break; case '0': //比較結果得出表示式錯誤 printf("input error!\n"); exit(1); } } x = os.top(); } c = ns.top(); return c; } int main(void) { float c; printf("please input expression (end in #):"); c = EvaluateExpression(); printf("result = %f\n", c); getchar(); } /* 測試資料 20-2*(5-1-3*(4-1)-2)-6# 1+(2+3)*[3+6]/{4+5}+{[8*7]}# 1+{[2+3]}# */