借助栈实现表达式的计算

这两天要复习准备考试,博客没有及时更新。另一方面,后缀表达式的转化及求值的程序始终没有写好,让我异常苦恼,心情也是莫名烦躁。现在表达式求值的程序已基本实现,仍有不足之处需要改进,各位可以参考,由于时间关系,无法细致讲解。将在考完试后的更新中加以补充,各位先看代码后的注释吧,注释还是比较详细的,代码如下

#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 100
#define MAXOP 32
typedef char elemtype;
typedef int status;
/*定义运算符优先级*/
typedef struct calc{
    elemtype ch;
    int pri;
}calc;
/*同一运算符在栈内和栈外优先级不同,需要加一个数字进行区分*/
calc inpri[]={{'=',0},{'(',1},{'*',5},{'/',5},{'+',3},{'-',3},{')',6}};
calc outpri[]={{'=',0},{'(',6},{'*',4},{'/',4},{'+',2},{'-',2},{')',1}};

/*定义运算符栈*/
typedef struct sqstack{
    elemtype data[MAXSIZE];
    int top;
}sqstack;

/*定义运算结果栈*/ 
typedef struct value{
    float suffixvalue[MAXSIZE];
    int top;
}value;

/*定义栈操作
***************************************/
status traversestack(sqstack *s){
    int i=0;
    for(i=s->top;i>=0;i--){
        printf("%d ",s->data[i]);
    }
    printf("\n");
}

/*初始化运算符栈*/ 
status initstack(sqstack *s){
    s->top=-1;//置空栈 
}

/*初始化运算结果栈*/ 
status initvstack(value *V){
    V->top=-1;
    return OK;
}

//将元素压入栈 
status push(sqstack *s,elemtype data)
{
    if(s->top==MAXSIZE-1){
        return ERROR;//判断栈是否已满 
    }
    else{
        s->top++;
        s->data[s->top]=data;
    }
    return OK;
}


//返回栈长
status stacklength (sqstack *s){
    return s->top+1;
}

//出栈
status pop(sqstack *s,elemtype * data){
    if(s->top==-1){
        printf("空栈\n");
        return ERROR;
    }
    else{
        *data=s->data[s->top];
        s->top--;
    }
}

/*取栈顶元素*/
status gettop(sqstack *S,elemtype *ch){
    if(S->top==-1)
        return ERROR;
    else
        *ch=S->data[S->top];
        return OK;
}

/*定义栈操作结束 
***************************************/

/*定义运算符相关操作
****************************************/
/*求栈外操作符优先级*/
status Inpri(elemtype op){
    int i=0;
    for(i=0;i<MAXOP;i++){
        if(op==inpri[i].ch)
           return inpri[i].pri;
    }
} 

/*求栈内操作符优先级*/
status Outpri(elemtype op){
    int i=0;
    for(i=0;i<MAXOP;i++){
        if(op==outpri[i].ch)
           return outpri[i].pri;
    }
}

/*判断两运算符优先级关系*/
status precede(elemtype opin,elemtype opout){
    if(Inpri(opin)>Outpri(opout))
       return 1;
    else if(Inpri(opin)<Outpri(opout))
       return -1;
    else
       return 0;
}

/*判断是否为运算符*/
status isop(elemtype ch){
    if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')')
         return TRUE;
    else
         return FALSE; 
}

/*将中缀表达式转换为后缀表达式*/
status trans(char * infix,char suffix[]){
    sqstack S;
    initstack(&S);
    push(&S,'=');/*先让一个等号入栈,作为标记*/
    char ch;
    int i=0,j=0;
    while(*infix!='\0'){
        /*是数字的情况*/
        if(!isop(*infix)){
            while((*infix)>='0'&&(*infix)<='9'){
                suffix[j++]=*infix;
                infix++;
            }
            suffix[j++]='#';/*数字与数字之间用空格隔开*/
        }
        /*是运算符的情况*/
        else{
            gettop(&S,&ch);
            switch(precede(ch,*infix)){
                case 1:/*栈顶高于栈外*/
                    suffix[j++]=ch;/*栈顶出栈直到栈顶元素优先级低于栈外为止*/ 
                    pop(&S,&ch);
                    //infix++;/*向后遍历*/ 
                    break;
                case 0:/*栈顶等于栈外,只有括号会出现此情况*/ 
                    pop(&S,&ch);/*直接出栈*/ 
                    infix++;
                    break;
                case -1:/*栈顶低于栈外*/ 
                    push(&S,*infix);/*入栈即可*/ 
                    infix++;
                    break;
            }
        } 
    }/*while(*infix!='/0')*/
    /*循环结束,开始输出后缀表达式*/
    pop(&S,&ch);
    while(ch!='='){/*等号代表了表达式的开头*/ 
        suffix[j++]=ch;
        pop(&S,&ch);
    }
}

/*计算后缀表达式的值*/
float compute(char suffix[]){
    value V;
    initvstack(&V);
    char ch;
    int t=0;
    float d;
    ch=suffix[t];
    t++;
    while(ch!='\0'){
        /*让栈顶两元素出栈进行运算*/
        switch(ch){
            case '+':
                V.suffixvalue[V.top-1]=V.suffixvalue[V.top-1]+V.suffixvalue[V.top];
                V.top--;
                break;
            case '-':
                V.suffixvalue[V.top-1]=V.suffixvalue[V.top-1]-V.suffixvalue[V.top];
                V.top--;
                break;
            case '/':
                if(V.suffixvalue[V.top]){
                    V.suffixvalue[V.top-1]=V.suffixvalue[V.top-1]/V.suffixvalue[V.top];
                    V.top--;
                    break;
                }
                else{
                    printf("除零错误\n");
                    return ERROR;
                }
            case '*':
                V.suffixvalue[V.top-1]=V.suffixvalue[V.top-1]*V.suffixvalue[V.top];
                V.top--;
                break;
            /*如果后缀表达式中有数字*/ 
            default:
                d=0;
                while(ch>='0'&&ch<='9'){
                    d=10*d+ch-'0';/*将字符转换成数字*/ 
                    ch=suffix[t];/*向后遍历*/ 
                    t++;
                }
                V.top++;
                V.suffixvalue[V.top]=d;/*将转换好的入栈*/ 
        }
        ch=suffix[t];/*更新ch的值*/
        t++;
    }
    return V.suffixvalue[V.top];/*返回栈顶值作为运算结果*/ 
}

int main(void){
    char infix[]="(56-20)/(4+2)";
    char suffix[200];
    trans(infix,suffix);
    printf("中缀表达式:%s\n",infix);
    printf("后缀表达式:%s\n",suffix);
    printf("后缀表达式的值为%f",compute(suffix));
    return 0;
} 

再次吐槽:真心难啊…………

2016-04-21日更新:
今天复习了表达式求值问题,还是感到存在一些问题,还是对算法的理解理解不够透彻造成的。
问题主要出现在后缀表达式转中缀表达式的过程中

status trans(char *infix,char suffix[]){
    elemtype ch;
    sqstack S;
    int i=0;
    initstack(&S);
    push(&S,'=');
    while(*infix!='\0'){
        if(!isop(*infix)){
            while(*infix<='9'&&*infix>='0'){
                suffix[i++]=*infix;
                infix++;
            }
            suffix[i++]='#';
        }
        else{
            gettop(&S,&ch);
            switch(precede(ch,*infix)){
                case 1:
                    suffix[i++]=ch;
                    pop(&S,&ch);
                    break;
                case 0:
                    pop(&S,&ch);
                    infix++;
                    break;
                case -1:
                    push(&S,*infix);
                    infix++;
                    break;
            }
        }
    }/*while(*infix!='\0')*/
    pop(&S,&ch);
    suffix[i]=ch;
    while(ch!='='){
        suffix[i++]=ch;
        pop(&S,&ch);
    }
}

在这段代码的switch语句中,在处理case 0时,对于括号的优先级的理解有所遗忘。正确的处理方式是当栈外为右括号,栈内为左括号时,直接出栈即可。
在compute函数中,忘了写default语句,导致当遇到后缀表达式中的数字时无法处理。
以上就是今天的错误,要引以为戒。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值