帶括號的表達式求值


問題和上一篇博客一樣,只是在表達式中加入了括號。

思路和上一篇博客的差異不大,只是在處理左右括號的優先級時需要注意一下:

1.左括號的優先級僅高於#;

2.但是遇見左括號時,不用和OPTR棧頂元素進行優先級比較,直接強制進OPTR棧;

3.遇到右括號,退OVS棧兩次,退OPTR棧一次,進行相應的運算操作,將計算結果壓入OVS棧,直到OPTR棧頂元素時左括號為止,並將左括號彈出OPTR棧;

 

代碼如下:

#include<stdio.h> #include<stdlib.h> #include<math.h> #include<stdbool.h> typedef struct node{ int data;//無論對於運算符還是運算數,都用int型變量來保存 
    node *next; }LinkStackNode, *LinkStack; void InitStack(LinkStack *S){//初始化鏈棧 
    *S = (LinkStack)malloc(sizeof(LinkStackNode)); (*S)->next = NULL; } int Push(LinkStack top, int x){// 進棧操作 
    LinkStackNode *temp; temp = (LinkStackNode*)malloc(sizeof(LinkStackNode)); if(temp == NULL) return 0; temp->data = x; temp->next = top->next; top->next = temp; return 1; } int Pop(LinkStack top, int *x){//出棧操作 
    LinkStackNode *temp; temp = top->next; if(temp == NULL) return 0; *x = temp->data; top->next = temp->next; free(temp); return 1; } int GetNum(char ch){//返回字符對應的數字 
    return ch - '0'; } bool IsEmpty(LinkStack top){//棧為空返回假 
    if(top->next == NULL) return false; return true; } int GetTop(LinkStack top){//返回棧頂元素 
    if(top->next == NULL) return 1; return top->next->data; } /*進行運算符優先級比較,用表列出所有可能出現的情況, ch1對應行,ch2對應列,每次找到對應的位置,直接返回 優先級比較結果*/ 
char Compare(char ch1, char ch2){ int i, j; char rela[7][7] = {{'=', '<', '<', '<', '<', '<', '<'}, {'>', '=', '=', '<', '<', '<', '>'}, {'>', '=', '=', '<', '<', '<', '>'}, {'>', '>', '>', '=', '=', '<', '>'}, {'>', '>', '>', '=', '=', '<', '>'}, {'>', '>', '>', '>', '>', '=', '>'}, {'>', '<', '<', '<', '<', '<', '='}, }; switch(ch1){ 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(ch2){ 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; } return rela[i][j]; } int Calculate(int a, char op, int b){//計算 a op b 的值 
    int c; switch(op){ case '-': c = a - b; break; case '+': c = a + b; break; case '*': c = a * b; break; case '/': c = a / b; break; case '^': c = pow(a, b); break; default : c = 0; } return c; } bool IsOperation(char ch){//判斷是不是操作符 
    if(ch == '#' || ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '^' ) return true; return false; } int ExpEvaluation(){//實現 
 LinkStack ovs, optr; InitStack(&ovs); InitStack(&optr); Push(optr, (int)'#'); char ch = getchar(); int num = 0, a, b, t, op, zan; while(ch != '#' || (char)GetTop(optr) != '#'){ while(ch >= '0' && ch <= '9'){//如果數字不是一位數字,便把字符轉化為數字 
            num = num * 10 + GetNum(ch); ch = getchar(); } if(num != 0){//如果num不為0便進OVS棧 
 Push(ovs, num); num = 0;//把num置零 
 } else if(IsOperation(ch)){ switch(Compare(ch, (char)GetTop(optr))){//對運算符優先級進行比較,實現對應三種關系的操作 
                case '>': Push(optr, (int)ch); ch = getchar(); break; case '=': case '<': Pop(optr, &op); Pop(ovs, &a); Pop(ovs, &b); t = Calculate(b, (char)op, a); Push(ovs, t); break; } } else if(ch == '('){//遇見左括號直接進OPTR棧 
            Push(optr, (int)ch); ch = getchar(); } else if(ch == ')'){//遇見左括號 
            while((char)GetTop(optr) != '('){//直到棧頂元素為左括號結束本次循環 
                Pop(optr, &op); //OPTR退棧一次 
                Pop(ovs, &a);//OVS退棧兩次 ,進行相應的計算,把結果壓入OVS棧中 
                Pop(ovs, &b); t = Calculate(b, (char)op, a); Push(ovs, t); } Pop(optr, &op);//彈出左括號操作 
            ch = getchar(); } } t = GetTop(ovs);//取棧頂元素,返回最終計算結果 
    return t; } int main(){ printf("\n\nPlease input an expression(Ending with '#'):\n"); int ans = ExpEvaluation(); printf("%d\n", ans); return 0; }

運行結果:


免責聲明!

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



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