带括号的表达式求值

问题和上一篇博客一样,只是在表达式中加入了括号。

思路和上一篇博客的差异不大,只是在处理左右括号的优先级时需要注意一下:

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("

Please input an expression(Ending with '#'):
");
    int ans = ExpEvaluation();
    printf("%d
", ans);
    return 0;
}

运行结果:

种一棵树最好的时间是十年前,其次是现在。
原文地址:https://www.cnblogs.com/HyattXia/p/9798208.html