带括号的表达式求值


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

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

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