C語言之四則運算表達式求值(鏈棧)—支持浮點型數據,負數, 整型數據運算


 運算符間的優先級關系:

 

鏈棧結構體定義:

數據域使用字符串長度為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 }

 

 

運行結果:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM