棧在表示式計算過程中的應用【轉】
阿新 • • 發佈:2018-12-21
棧在表示式計算過程中的應用 :建立運算元棧和運算子棧。運算子有優先順序。
規則:
自左至右掃描表示式,凡是遇到運算元一律進運算元棧。
當遇到運算子時,如果它的優先順序比運算子棧棧頂元素的優先順序高就進棧。反之,取出棧頂運算子和運算元棧棧頂的連續兩個運算元進行運算,並將結果存入運算元棧,然後繼續比較該運算子與棧頂運算子的優先順序。
左括號一律進運算子棧,右括號一律不進運算子棧,取出運算子棧頂運算子和運算元棧頂的兩個運算元進行運算,並將結果壓入運算元棧,直到取出左括號為止。
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 100 enum link{PUSH, PUSH_NO}; typedef struct // 運算數 { int num[MAX]; int top; }OP_num; typedef struct // 運算子 { char str[MAX]; int top; }OP_ch; // 運算數置空棧 void SETNULL_num (OP_num* s) { s->top = -1; } // 運算子置空棧 void SETNULL_ch (OP_ch* s) { s->top = -1; } // 判斷是否是數字,是返回1 不是返回0 int is_num (char ch) { if (ch >= '0' && ch <= '9') { return 1; } else { return 0; } } // 數字入棧 int PUSH_num (OP_num *s, int data) { if ((MAX - 1) == s->top) { return 0; } else { s->num[++s->top] = data; } } // 運算子入棧 int PUSH_ch (OP_ch* s, char ch) { if ((MAX - 1) == s->top) { return 0; } else { s->str[++s->top] = ch; } } // 判斷是否將運算子入棧 int jud (OP_ch* s, char ch) { if (-1 == s->top) // 判斷是否是空棧 { return PUSH; } else { switch (s->str[s->top]) // 根據棧頂運算判斷是否進棧 { case '+': // 當棧頂是'+-'時,只有‘+-)’不進棧 case '-': { if (ch == '+' || ch == '-' || ch == ')') { return PUSH_NO; } else { return PUSH; } break; } case '*': case '/': { if ('(' == ch) { return PUSH; } else { return PUSH_NO; } break; } case '(': { return PUSH; break; } } } } // 數字出棧 int Pop_num (OP_num* s) { return (s->num[s->top--]); } // 運算子出棧 void Pop_ch (OP_ch* s) { s->top--; } // 進行運算 void operate (OP_ch* s_ch, OP_num* s_sum) { int a = Pop_num(s_sum); // 取第一個數 int b = Pop_num(s_sum); // 取第二個數 int result; // 根據當前運算子棧頂的符號來判斷進行何種運算 switch (s_ch->str[s_ch->top]) { case '+': result = a + b; break; case '-': result = b - a; break; case '*': result = a * b; break; case '/': result = b / a; break; } PUSH_num (s_sum, result); // 將運算結果入棧 } int main() { OP_num sdata; OP_ch soper; SETNULL_num (&sdata); SETNULL_ch (&soper); int i = 0, len_str, t; char str[MAX]; char str_num[MAX]; // 存放要轉化的數字 gets (str); // 輸入表示式 len_str = strlen (str); // 獲取表示式長度 while (str[i] != '\0') // 遍歷表示式 { if (is_num(str[i])) // 判斷是否是數字 { t = 0; while (is_num(str[i])) { str_num[t++] = str[i++]; //將表示式中的數字進行儲存,用於轉化為對應的整形數 } str_num[t] = '\0'; PUSH_num (&sdata, atoi(str_num)); // 遇到算數符號的時候讓符號前面的數進棧 } else { if (PUSH == jud(&soper, str[i])) { PUSH_ch (&soper, str[i]); } else { if (str[i] != ')') // ')'不讓其入棧所以單獨列出來討論 { operate (&soper, &sdata); // 進行一次運算並一處棧頂運算子 Pop_ch(&soper); // 符號出棧 PUSH_ch (&soper, str[i]); // 進行壓棧 // 相當於用當前的運算子替換了剛才棧頂的運算子號 } else // 遇到')' // 不斷取字元運算 知道遇到 ')' { do { operate (&soper, &sdata); Pop_ch (&soper); }while (soper.str[soper.top] != '('); Pop_ch (&soper); // 將‘(’彈出棧空間 } } i++; } } while (soper.top != -1) { operate (&soper, &sdata); Pop_ch (&soper); } printf ("%d\n", sdata.num[sdata.top]); return 0; }