【数据结构】栈的运用(二)无括号表达式求值修正版

无括号表达式修正

  • 博主换了clion之后发现自己前面写的代码有很多遗漏的地方,以修正无括号表达式求值那篇提高自己水平。
  • 前面无括号表达式求值是不能求大于1位数的运算的,我对代码进行了修改让其可以求大于2位数的运算同时完善了许多语句和逻辑。

代码收获

  • clion有时候会提示xxx can be pointer to const,意思是你下面那段代码并没有修改xxx指针指向的值,建议你直接传值或者传const指针。
  • 经过clion的提示发现getchar()函数的返回值原来是int…需要强制转换一下,当然你不转换也能运行。
  • 经clion提示,atoi函数并不可靠,用strtol函数比较可靠,虽然我里面没让他返回值。
  • 无括号表达式求值逻辑并不难,主要就是栈的运用。
  • 能进行多位运算原理是我将输入语句存入队列再出列判断时判断队列下一个要出的是不是数字。如果是数字保存在中间变量末尾,如果不是,保存在中间变量末尾并把中间变量入栈,中间变量置空。特别注意判断下一个要出的队列时最后一个元素的操作。

栈的归档

栈的存储结构(一)顺序栈
栈的存储结构(二)双端栈
栈的存储结构(三)链栈
栈的运用(一)无括号表达式求值
栈的运用(二)无括号表达式求值修正版

# include <stdio.h>
# include <stdlib.h>
# define MAXSIZE 100
typedef struct stack{
    int top;
    int ele[MAXSIZE];
}stacknum,*stacknump;
typedef struct stackop{
    int top;
    char ele[MAXSIZE];
}stackop,*stackopp;
typedef struct que{
    char ele[MAXSIZE];
    int front,rear;
}quene,*quenep;
//初始化 quene是队列 stackop是操作栈 stacknum是数字栈
void InitialStack(stacknump* ST,stackopp* OP,quenep* QE){
    *ST=(stacknump)malloc(sizeof(stacknum));
    *OP=(stackopp)malloc(sizeof(stackop));
    *QE=(quenep)malloc(sizeof(quene));
    (*ST)->top = -1;
    (*OP)->top = -1;
    (*QE)->rear=0;
    (*QE)->front=0;//
}
char getops(stackopp OP){//获得栈顶的元素
    return OP->ele[OP->top];
}
int compareop(char a,stackopp OP){//比较操作符优先级
    char b;
    b = getops(OP);
    int aa,bb;
    switch(a){//按获取的操作符的优先级给aa bb 赋值,比较aa和bb从而知道哪个操作符优先级高
        case '$': {
            aa=0;
            break;
        }
        case '+':
        case '-':{
            aa=1;
            break;
        }
        case '*':
        case '/':{
            aa=2;
            break;
        }
        default:{
            printf("操作符入栈错误\n");
            aa=-100;
            break;
        }
    }
    switch(b){
        case '$': {
            bb=0;
            break;
        }
        case '+':
        case '-':{
            bb=1;
            break;
        }
        case '*':
        case '/':{
            bb=2;
            break;
        }
        default:{
            printf("操作符入栈错误\n");
            bb=-100;
            break;
        }
    }
    if(aa!=-100||bb!=-100){
        if(aa-bb>0){//如果第一个操作符优先级比第二个操作符优先级高
            return 1;
        }else if(aa-bb==0){
            return 0;
        }else{
            return -1;
        }
    }
}
int excuit(int num2,int num1,char ops){//num1和num2进行运算
    switch(ops){
        case '+':{
            return num2+num1;
        }
        case '-':{
            return num2-num1;
        }
        case '*':{
            return num2*num1;
        }
        case '/':{
            return num2/num1;
        }
        default:{
            printf("获取操作符错误\n");
            return 0;
        }
    }
}
int PushQuene(quenep QE,char x){
    if(QE->rear+1%MAXSIZE==QE->front){
        printf("队列满\n");
        return 1;
    }else{
        QE->ele[QE->rear]=x;
        QE->rear=(QE->rear+1)%MAXSIZE;
    }return 0;
}
int PopQuene(quenep QE,char*x){
    if(QE->front==QE->rear){
        printf("队列空\n"); return 1;
    }else{
        *x = QE->ele[QE->front];
        QE->front=(QE->front+1)%MAXSIZE;
    }
}

int CalculateStack(stacknump ST,stackopp OP,quenep QE){
    printf("输入数字与操作符,按$结束\n");
    OP->top++;
    OP->ele[OP->top]='$';//先进行入符号栈$
    int flag = 1;
    while(flag){
        char  d;//
        d = (char)getchar();
        //先入队列
        if(d!='$'){
            PushQuene(QE,d);
        }else{
            flag=0;
            char ran;
            ran='$';//最后一个$入队列
            PushQuene(QE,ran);
        }
    }getchar();
    int flag3=1;
    char tmp[100]="\0";//初始化一个中间数组存放数字
    while(flag3){
        char c;
        PopQuene(QE,&c);//出队列取得队列第一个c
        if(c!='$'){
            switch(c){
                case '+':
                case '-':
                case '*':
                case '/':{
                    //加减乘除入符号栈
                    int flag2=1;
                    while(flag2){
                        int prime;
                        prime = compareop(c,OP);//比较要入栈的符号和栈内优先级
                        if(prime>0){
                            OP->top++;//如果优先级高,那么入栈,进入下一个循环
                            OP->ele[OP->top]=c;
                            flag2=0;
                        }else{//否则,取出数字栈2个数和操作栈的1个操作符进行运算,得到的数字再入数字栈
                            //由于c没入栈,继续循环比较c的优先级,直到c大于栈顶优先级为止
                            int num1,num2;
                            char ops;
                            num1 =ST->ele[ST->top];
                            ST->top--;
                            num2 = ST->ele[ST->top];
                            ST->top--;
                            ops = getops(OP);
                            OP->top--;
                            int res;
                            res = excuit(num2,num1,ops);//得到运算结果
                            ST->top++;
                            ST->ele[ST->top]=res;//入数字栈
                        }
                    }
                    break;
                }
                default:{//默认情况就是数字字符,检测队列里下一个是不是数字字符,如果是数字字符,把当前字符存入tmp尾
                    //如果不是字符,也存入tmp尾,然后把tmp如入数字栈
                    if('0'<=c&&c<='9'){
                        char pre;
                        if(QE->front!=QE->rear){
                        pre = QE->ele[QE->front];}//看队列顶部
                        else pre='+';//如果队列空了,那么相当于队列后一个是符号
                        switch(pre){
                            case '+':
                            case '$':
                            case '-':
                            case '*':
                            case '/':{
                                int shu,numb,base=10;//下一个出队的是符号
                                for(shu=0;tmp[shu]!='\0';shu++);//shu代表尾0的位置
                                tmp[shu]=c;
                                tmp[shu+1]='\0';//把c加到末尾
//                              numb=atoi(tmp);//建议不使用atoi因为不能判断转换失败,改用strtol
                                numb=strtol(tmp,NULL,base);//第二个变量是存放转换失败字符串,需要二重指针。如果是NULL就是不传回其他数字
                                ST->top++;
                                ST->ele[ST->top]=numb;//入数字栈
                                tmp[0]='\0';//把tmp重置为尾0
                                break;
                            }
                            default : {//下一个是数字就把当前数字存到tmp中
                                int shu2;
                                for (shu2 = 0; tmp[shu2] != '\0'; shu2++);
                                tmp[shu2] = c;
                                tmp[shu2 + 1] = '\0';
                                break;
                            }
                        }
                    }
                    break;
                }
            }
        } else{//如果字符是$ 说明队列出完了
            flag3= 0;
            //把数字栈的进行计算,如果符号栈不是0,-1是空,0是$在里面
            while(OP->top!=0){
                //取出栈顶2数字,如果无符号是不会剩2数字的
                int num3,num4;
                char ops2;
                num3 =ST->ele[ST->top];
                ST->top--;
                num4 = ST->ele[ST->top];
                ST->top--;
                ops2 = getops(OP);
                OP->top--;
                int res2;
                res2= excuit(num4,num3,ops2);//运算
                ST->top++;
                ST->ele[ST->top]=res2;//存入数字栈
            }
        }
    }
    printf("结果是%d",ST->ele[0]);//最终结果数字栈第一个
    return 0;
}
void main(){
    stackopp OP;
    stacknump ST;
    quenep QE;
    InitialStack(&ST,&OP,&QE);
    CalculateStack(ST,OP,QE);
}

输入数字与操作符,按$结束
2521+24*21-213*3+6324$
2521+24*21-213*3+6324$
结果是8710

猜你喜欢

转载自blog.csdn.net/yehuozhili/article/details/83048955