这两天要复习准备考试,博客没有及时更新。另一方面,后缀表达式的转化及求值的程序始终没有写好,让我异常苦恼,心情也是莫名烦躁。现在表达式求值的程序已基本实现,仍有不足之处需要改进,各位可以参考,由于时间关系,无法细致讲解。将在考完试后的更新中加以补充,各位先看代码后的注释吧,注释还是比较详细的,代码如下
#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语句,导致当遇到后缀表达式中的数字时无法处理。
以上就是今天的错误,要引以为戒。