運算符間的優先級關系:
鏈棧結構體定義:
數據域使用字符串長度為20的字符數組(故需要注意判斷讀取的字符串是運算符還是數值)
可支持浮點型數據,負數, 整型數據的運算
float EvaluateExpression() 函數實現步驟:
1)初始化OPTR棧和OPND棧,將表達式起始符 “#” 壓入OPTR棧。
2)掃描表達式,讀入第一個字符串str,如果表達式沒有掃描完畢至 "#" 或壓入OPTR的棧頂元素不為 "#" 時,則循環執行以下操作:
——>使用 str_to_float() 函數判斷輸入的字符串str是否是運算符
——>如果str不是運算符,則壓入OPND棧,讀取下一個字符串str
——>如果字符串str是運算符,使用 Precede() 函數獲取OPTR棧頂元素的運算符和字符串str的運算符的優先級:
——>若是 ‘<’ ,則字符串str壓入OPTR棧,讀入下一個字符串str
——>若是 ‘>’ ,則彈出OPTR棧頂的運算符字符串,從OPND棧彈出兩個數值字符串,使用 Operate() 函數對兩個字符串進行運算,將得到的浮點型運算結果使用 float_to_str() 函數轉換成字符串型數據,壓入OPND棧
——>若是 ‘=’ ,則OPTR的棧頂元素是 "(" 且 str 是 ")" ,這時彈出OPTR棧頂的 "(" ,相當於括號匹配成功,然后讀入下一字符串str
3)OPND棧頂元素記為表達式求值結果,輸出運算結果。
實現代碼(.cpp后綴文件)
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<math.h> 5 6 #define inf float(0x3f3f3f3f) 7 #define MAXSIZE 100 8 9 char priority[7] = {'+', '-', '*', '/', '(', ')', '#'}; 10 11 char priority_relationship[7][7] = { 12 {'>', '>', '<', '<', '<', '>', '>'}, 13 {'>', '>', '<', '<', '<', '>', '>'}, 14 {'>', '>', '>', '>', '<', '>', '>'}, 15 {'>', '>', '>', '>', '<', '>', '>'}, 16 {'<', '<', '<', '<', '<', '=', ' '}, 17 {'>', '>', '>', '>', ' ', '>', '>'}, 18 {'<', '<', '<', '<', '<', ' ', '='} 19 }; // 各個運算符之間的優先級關系 20 21 int get_index(char str[]) 22 {// 獲取相應運算符的索引 23 for(int i = 0; i < 7; i++) 24 { 25 if(str[0] == priority[i]) return i; 26 } 27 printf("未找到匹配的字符\n"); 28 } 29 30 char Precede(char inside_data[], char input_data[]) 31 {// 獲取兩個運算符之間的優先級關系 32 int inside_index = get_index(inside_data); 33 int input_index = get_index(input_data); 34 35 return priority_relationship[inside_index][input_index]; 36 } 37 38 typedef struct StackNode 39 { 40 char data[MAXSIZE]; // 壓入棧里面的數據都是字符型,在進行運行時,記得將字符型數字轉換為浮點型數字 41 struct StackNode *next; 42 }StackNode, *LinkStack; 43 44 void InitStack(LinkStack &S) 45 {// 構造一個空棧S,棧頂指針置空 46 S = NULL; 47 } 48 49 void Push(LinkStack &S, char data[]) 50 {// 在棧頂插入元素data 51 StackNode *p; 52 53 p = (StackNode *)malloc(sizeof(StackNode)); // 生成新的結點 54 strcpy(p->data, data); // 將新結點的數據域置為data 55 p->next = S; // 將新結點插入棧頂 56 S = p; // 修改棧頂指針為p 57 } 58 59 char *Pop(LinkStack &S) 60 {// 刪除S的棧頂元素, 用data返回其值 61 char data[MAXSIZE]; 62 if(S == NULL) printf("錯誤!!!\n棧為空, 無法執行刪除命令..."); 63 else 64 { 65 StackNode *p; 66 67 strcpy(data, S->data); // 將棧頂元素賦給data 68 p = S; // 用p臨時保存棧頂元素的空間,以備釋放 69 S = S->next; //修改棧頂指針 70 free(p); // 釋放原棧頂元素的空間 71 return data; 72 } 73 } 74 75 char *GetTop(LinkStack &S) 76 {// 獲取棧頂元素 77 if(S != NULL) 78 return S->data; 79 else 80 { 81 printf("錯誤!!!\n棧頂為空"); 82 return "0"; 83 } 84 } 85 86 float str_to_float(char *str) 87 {// 將字符串數據轉換成浮點型數據 88 float num = 0; 89 int state_1 = 0; // 用於判斷是否讀取到小數點的狀態值, 0代表還沒有讀取到 90 int state_2 = 0; //用於判斷是否讀取到負號的狀態值, 0代表還沒有讀取到 91 while(( *str != '\0' && *str >= '0' && *str <= '9') || *str == '.' || (*str == '-' && *(str + 1) != '\0')) 92 {// 注意判斷小數點和負號 93 if(*str == '.') state_1 = 1; // 當讀取到小數點的時候, 狀態值state_1賦值為1 94 else if(*str == '-') state_2 = 1; // 當讀取到負號的時候, 狀態值state_2賦值為1 95 else 96 { 97 if(state_1 == 0) num = num * 10 + (*str - '0'); 98 else 99 { 100 num += (*str - '0') * pow(0.1, state_1); 101 state_1++; 102 } 103 } 104 str++; 105 } 106 if(*str != '\0') return inf; 107 else if(state_2 == 1) 108 { 109 return num * -1; 110 } 111 else return num; 112 } 113 114 char *float_to_str(float num) 115 {// 將浮點型數據裝換成字符串數據,保留浮點型數據小數點后4位的值 116 char str[MAXSIZE]; 117 sprintf(str, "%.4f", num); // 保留小數點后4位 118 return str; 119 } 120 121 122 float Operate(char a[], char theta[], char b[]) 123 {//執行運算 124 float a_num = str_to_float(a); 125 float b_num = str_to_float(b); 126 127 if(theta[0] == '+') return a_num + b_num; 128 else if(theta[0] == '-') return a_num - b_num; 129 else if(theta[0] == '*') return a_num * b_num; 130 else if(theta[0] == '/') return a_num / b_num; 131 else printf("錯誤!!!\n無該運算符"); 132 } 133 134 void EvaluateExpression() 135 { 136 StackNode *OPND, *OPTR; 137 char str[MAXSIZE]; 138 char theta[MAXSIZE]; 139 char a[MAXSIZE]; 140 char b[MAXSIZE]; 141 142 InitStack(OPND); // 初始化棧 OPND 143 InitStack(OPTR); // 初始化棧 OPTR 144 Push(OPTR, "#"); // 將 "#" 壓入棧OPTR 145 146 printf("請輸入算術表達式(支持負數,浮點型數據),每個值用空格隔開輸入,並以#結束\n"); 147 scanf("%s", str); 148 while(str[0] != '#' || GetTop(OPTR)[0] != '#') 149 { 150 if(str_to_float(str) != inf) 151 { // 如果str不是運算符,則壓入OPND棧,讀取下一個字符串str 152 Push(OPND, str); // 將字符串str壓入OPTR棧 153 scanf("%s", str); // 讀入下一個字符串str 154 } 155 else 156 { // 如果字符串str是運算符,使用 Precede() 函數獲取OPTR棧頂元素的運算符和字符串str的運算符的優先級 157 switch (Precede(GetTop(OPTR), str)) // 使用 Precede() 函數獲取相應優先級 158 { 159 case '<': 160 Push(OPTR, str); // 將字符串str壓入OPTR棧 161 scanf("%s", str); // 讀入下一個字符串str 162 break; 163 case '>': 164 strcpy(theta, Pop(OPTR)); // 彈出OPTR棧頂的運算符字符串並賦值給變量 theta 165 strcpy(b, Pop(OPND)); // 彈出OPND棧頂的數值字符串並賦值給變量 b 166 strcpy(a, Pop(OPND)); // 彈出OPND棧頂的數值字符串並賦值給變量 a 167 char temp_str[MAXSIZE]; 168 strcpy(temp_str, float_to_str(Operate(a, theta, b))); // 根據相應的三個字符串進行運算,把結果賦給temp_str 169 Push(OPND, temp_str); // 將運算結果 temp_str 壓入OPND棧 170 break; 171 case '=': 172 Pop(OPTR); // 彈出OPTR棧頂的運算符字符串 173 scanf("%s", str); // 讀入下一個字符串str 174 break; 175 default: 176 printf("錯誤!!!\n該優先級不存在!!!"); 177 } 178 } 179 } 180 printf("%s\n", GetTop(OPND)); 181 } 182 183 int main(void) 184 { 185 EvaluateExpression(); 186 187 system("pause"); 188 return 0; 189 }
運行結果: