• 【数据结构】book3_3 表达式求值


    #include<iostream>
    #include <stdlib.h>
    using namespace std;
    
    typedef int Status;
    const int TRUE=1;
    const int FALSE=0;
    const int OK=1;
    const int ERROR=0;
    const int INFEASIBLE=-1;
    const int overflow=-2;
    const int STACK_INIT_SIZE=100;
    const int STACKINCREMENT=10;
    
    
    
    typedef struct{
        char *base;
        char *top;
        int stacksize;
    }SqStack;
    
    //构造一个空栈
    Status InitStack(SqStack &S)
    {
        S.base=(char*)malloc(sizeof(char)*STACK_INIT_SIZE); 
        if(!S.base) exit(overflow);
        S.top=S.base;
        S.stacksize=STACK_INIT_SIZE;
        return OK;
    }
    
    Status GetTop(SqStack S,char &e)
    {
        if(S.top==S.base) return ERROR;
        e=*(S.top-1);
        return OK;
    }
    
    Status Push(SqStack &S,char e)
    {
        if(S.top-S.base>=S.stacksize)
        {
            S.base=(char*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(char));  
            if(!S.base)exit(overflow);
            S.top=S.base+S.stacksize;
            S.stacksize+=STACKINCREMENT;
        }
        *S.top++=e;
        return OK;
    }
    
    Status Pop(SqStack &S,char &e)
    {
        if(S.top==S.base) return ERROR;
        e=*--S.top;
        return OK;
    }
    
    Status StackEmpty(SqStack S){
        if(S.base==S.top)
            return TRUE;
        else
            return FALSE;
    }
    
    Status ClearStack(SqStack &S)
    {
        S.top = S.base ;
        return TRUE;
    }
    
    Status DestroyStack(SqStack &S)
    {
        if(S.base!=NULL)
        {
            free(S.base);
            S.stacksize=0;
            S.top=NULL;
        }
        return TRUE;
    }
    #include"book3_3.h"
    
    #define ND 0  //操作数标志
    #define TR 1  //操作符标志
    
    //存放运算符的优先顺序的矩阵 op1是竖排的 op2是横排的 e表示错误 
    const static char Order[7][7]=      
        {{'>','>','<','<','<','>','>'}, // +
         {'>','>','<','<','<','>','>'}, // -
         {'>','>','>','>','<','>','>'}, // *
         {'>','>','>','>','<','>','>'}, // /
         {'<','<','<','<','<','=','e'}, // (
         {'>','>','>','>','e','>','>'}, // )
         {'<','<','<','<','<','e','='}}; // #
    //     +   -   *   /   (   )   #       
    
    
    //比较两个操作符的优先级 op1和op2的顺序不能错
    Status compOperator(char op1, char op2, char &result)
    {
        int t1=9,t2=9; 
        //找到两个操作符的优先级在矩阵中的位置
        switch(op1)   
        {
        case '+': t1=0; break;
        case '-': t1=1; break;
        case '*': t1=2; break;
        case '/': t1=3; break;
        case '(': t1=4; break;
        case ')': t1=5; break;
        case '#': t1=6; break;
        default: return ERROR; break;
        }
        switch(op2)
        {
        case '+': t2=0; break;
        case '-': t2=1; break;
        case '*': t2=2; break;
        case '/': t2=3; break;
        case '(': t2=4; break;
        case ')': t2=5; break;
        case '#': t2=6; break;
        default: return ERROR; break;
        }
    
        result=Order[t1][t2];
    
        if(result=='e') 
            return ERROR;
        else 
            return OK;
    }
    
    int decideNDorTR(char t)  //判断输入的字符是操作符还是操作数
    {
        if(t>=48&&t<=57)  //数字的ascii码范围
        {
            return ND;
        }
        else if(t=='+' || t=='-' || t=='*' || t=='/' || t=='(' || t==')' || t=='#')
        {
            return TR;
        }
        else
        {
            printf("error");
            return ERROR;
        }
    
    }
    
    char myCalculate(char op,char num1,char num2)  //字符型的运算符的计算
    {
        char num;
        switch(op)
        {
        case '+': num= num1+ num2; break;
        case '-': num= num1- num2; break;
        case '*': num= num1* num2; break;
        case '/': num= num1/ num2; break;
        default: printf("error");break;
        }
        return num;
    }
    
    //计算表达式的函数 注意运算结果大小不能超过255 char型
    char EvaluateExpression(char *p, int length) 
    {
        SqStack OPTR, OPND;
        InitStack(OPTR);
        InitStack(OPND);
        Push(OPTR,'#');
    
        
        while(*p != '')
        {
            char t = *(p++);
            int ND_TR=decideNDorTR(t); //判断是操作符 还是 操作数
    
            if(ND_TR == ND) //操作数
            {
                //操作数有可能是多位的
                char num=0;
                while(t>=48&&t<=57) //字符 0-9
                {
                    num = num * 10 + t - 48;
                    t=*(p++);
                }
                p--; //对于 12+3 这样的情况 在取完数后 p=3  +被取走了 需要退一个 把操作符还回去
                Push(OPND,num);
            }
            else if(ND_TR == TR) //操作符
            {
                char order;
                char op1;
                char op2= t;
                GetTop(OPTR,op1);
                compOperator(op1, op2, order);
                switch(order)
                {
                case '>':   //若栈中的操作符优先级高 则取出操作数的前两个做运算 把运算后的操作符弹出  运算结果压入
                    {
                        char num1,num2,num;
                        char tmp;
                        Pop(OPND,num2);
                        Pop(OPND,num1);
                        num = myCalculate(op1,num1,num2);
                        Push(OPND,num);
                        Pop(OPTR,tmp);
                        p--; //这里p要退回 让op2再进行新一轮判断 
                        break;
                    }
                case '<': //若栈中操作符优先级低 新操作符进栈
                    {
                        Push(OPTR,op2);
                        break;
                    }
                case '=': //()或# 弹出 脱括号
                    {
                        char tmp;
                        Pop(OPTR,tmp); break;
                    }
                default:
                    {
                        break;
                    }
                }
            }
    
    
        }
        char e;
        GetTop(OPND,e);
        return e;
    
    
    }
    
    void main()
    {
        char p[30]="(11+2)*3-28+123-52#";
        char ans;
        ans = EvaluateExpression(p, 30);
        printf("%d",ans);
        getchar();
    
    }

    写了好半天啊 关系总是理不清楚的感觉

  • 相关阅读:
    .NET框架设计—常被忽视的C#设计技巧
    判断网络是否链接
    ADO.NET入门教程(五) 细说数据库连接池
    爬虫selenium中截图
    爬虫极滑块验证思路
    Linux 磁盘分区、挂载
    linux中crontab任务调度
    第30课 操作符重载的概念
    第29课 类中的函数重载
    第28课 友元的尴尬能力
  • 原文地址:https://www.cnblogs.com/dplearning/p/3623136.html
Copyright © 2020-2023  润新知