借助栈实现表达式的计算

来源:互联网 发布:mac如何收藏网页的图片 编辑:程序博客网 时间:2024/05/20 18:44

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

#include<stdio.h>#include<stdlib.h>#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0#define MAXSIZE 100#define MAXOP 32typedef 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
原创粉丝点击