实验五 中缀表达式转化为后缀表达式算法昆工版本.docx
- 文档编号:29245906
- 上传时间:2023-07-21
- 格式:DOCX
- 页数:22
- 大小:20.29KB
实验五 中缀表达式转化为后缀表达式算法昆工版本.docx
《实验五 中缀表达式转化为后缀表达式算法昆工版本.docx》由会员分享,可在线阅读,更多相关《实验五 中缀表达式转化为后缀表达式算法昆工版本.docx(22页珍藏版)》请在冰豆网上搜索。
实验五中缀表达式转化为后缀表达式算法昆工版本
昆明理工大学信息工程与自动化学院学生实验报告
(2013—2014学年第三学期)
课程名称:
数据结构开课实验室:
信自楼4442013年11月12日
年级、专业、班
计科122班
学号
201210405204
姓名
邹华宇
成绩
实验项目名称
中缀表达式转化为后缀表达式算法及后缀表达式计算算法的实现
指导教师
胡守成
教师评语
教师签名:
年月日
注:
报告内容按实验须知中七点要求进行。
一、实验目的和要求
结合堆栈入栈出栈的特点解决实际问题。
输入一个含+、-、*、/、正整数和圆括号的合法的中缀表示的算术表达式,输出转化得到的后缀表达式,计算该表达式的运算结果。
调用直接计
算的函数
返回计算结果
后缀表达
式的计算
调用函数得到
后缀表达式
无错
调用容错函数
存在错误
报错并结束
得到用户输入
的中缀表达式
二、算法思想
三、所用仪器、材料(设备名称、型号、规格等)
联想计算机一台
MicrosoftVisualc++6.0
四、程序源代码
#include
#include
#include
typedefstruct/*定义结构体用来存储操作符*/
{
charop;/*存储字符*/
intlevel;/*存储优先级*/
}OpNode;
typedefstruct
{
OpNodeop[100];
inttop;
intsize;/*表示栈内元素的个数*/
}stack;/*定义符号栈*/
voidinit(stack*st)/*初始化栈*/
{
st->size=0;
st->top=0;
}
OpNodepop(stack*a)/*出栈*/
{
if(a->size==0)/*如果栈为空结束操作*/
{
exit(-1);
}
a->size--;
returna->op[--(a->top)];/*取出栈顶元素*/
}
voidpush(stack*a,OpNodeop)/*入栈函数*/
{
a->size++;
a->op[(a->top)++]=op;
}
OpNodetop(stack*a)/*观察栈顶函数*/
{
if(a->size==0)/*如果栈为空结束操作*/
{
printf("stackisempty\n");
exit(-1);
}
returna->op[(a->top)-1];/*只得到栈顶的值而不出栈*/
}
typedefstruct/*定义数值栈*/
{
doublenum[100];
inttop;/*栈顶指针*/
intsize;
}numstack;
voidinit2(numstack*st)/*初始化数值栈*/
{
st->size=0;
st->top=0;
}
doublepop2(numstack*a)/*数值栈出栈*/
{
if(a->size==0)/*出栈前的判空*/
{
exit(-1);
}
a->size--;
returna->num[--(a->top)];/*得到栈顶的值*/
}
voidpush2(numstack*a,doublenum)/*入栈*/
{
a->size++;
a->num[(a->top)++]=num;
}
voidmain()/*主函数*/
{charch='y';
voidchange(charstr[],charexp[]);/*声明要用到的各个函数*/
doubleCalResult(charexp[]);/*声明后缀表达式的计算函数*/
doubleDirectcalresult(charstr[]);
intcheck(charstr[],charchestr[100]);
charstr[100],exp[100],chestr[100];/*str存储原算术表达式,exp存储对应的后缀表达式,chestr存储容错字符'^'*/
do{
printf("算术表达式为:
\n");
gets(str);
if(check(str,chestr))/*调用容错函数*/
{printf("表达式错在:
\n");
printf("%s\n",str);
printf(chestr);/*根据输入情况指出错误的地方*/
printf("\n");
printf("Tryagian
:
");
while(ch=getchar(),ch!
='n'&&ch!
='y');
if(ch=='y'){system("pause");continue;}
if(ch=='n'){system("pause");exit(-1);}
}
change(str,exp);/*调用函数将中缀转化为后缀*/
printf("后缀表达式为:
%s\n",exp);
printf("运算结果为:
%f\n",CalResult(exp));/*调用函数计算后缀表达式*/
printf("Tryagian
:
");
while(ch=getchar(),ch!
='n'&&ch!
='y');
system("pause");
}while(ch!
='n');
}
voidchange(charstr[],charch[])/*将前缀表达式转化为后缀表达式*/
{
inti=0;/*str的索引*/
intk=0;
charc;/*字符串中取出的放在C中*/
stackst;/*定义符号栈*/
OpNodeop;
OpNodeops;
init(&st);/*初始化符号栈*/
c=str[i++];
while(c!
='\0')/*对字符串进行扫描*/
{
if((c>='0'&&c<='9')||c=='.')/*如果字符为数字或小数点*/
{
while((c>='0'&&c<='9')||c=='.')
{
ch[k++]=c;/*将字符直接放入数组中*/
c=str[i++];
}
ch[k++]='|';/*在其后面放入一个分隔符*/
}
if(c=='(')/*如果字符是左括号*/
{
op.op='(';
op.level=-1;/*定义其优先级为-1*/
push(&st,op);/*将左括号直接入栈*/
}
if(c==')')/*如果字符为右括号*/
{
op=top(&st);/*首先观察栈顶*/
while(st.size!
=0&&op.op!
='(')/*如果不是左括号并且栈不为空*/
{
op=pop(&st);/*出栈并存入数组中*/
ch[k++]=op.op;
if(st.size>0)/*再次检查栈是否为空,*/
op=top(&st);
elsebreak;/*为空就结束*/
}
pop(&st);/*去掉左括号*/
}
if(c=='+'||c=='-')/*如果是+-号*/
{
op.op=c;
op.level=1;/*优先级为1*/
if(st.size==0)
{
push(&st,op);/*如果此时栈为空直接入栈*/
}
else
{
ops=top(&st);/*观察栈顶*/
while(ops.level>=op.level)/*如果栈顶优先级高*/
{
ops=pop(&st);
ch[k++]=ops.op;/*将栈顶元素取出存入数组中*/
if(st.size>0)
ops=top(&st);/*进行判空操作,栈为空结束*/
else
break;
}
push(&st,op);/*此时栈顶优先级低,入栈*/
}
}
if(c=='*'||c=='/'||c=='%')/*如果是进行*/
{
op.op=c;
op.level=2;/*优先级为1*/
if(st.size==0)
{
push(&st,op);/*如果此时栈为空直接入栈*/
}
else
{
ops=top(&st);/*观察栈顶*/
while(ops.level>=op.level)/*如果栈顶优先级高*/
{
ops=pop(&st);/*将栈顶元素取出存入数组中*/
ch[k++]=ops.op;
if(st.size>0)
ops=top(&st);/*进行判空操作,栈为空结束*/
else
break;
}
push(&st,op);/*此时栈顶优先级低,入栈*/
}
}
c=str[i++];/*索引自加检索下一个字符*/
}
while(st.size!
=0)/*最后判断栈如果不为空*/
{
ops=pop(&st);/*取出栈内元素存入数组中*/
ch[k++]=ops.op;
}
ch[k]='\0';/*将\0作为结尾存入数组*/
}
doubleCalResult(charexp[])/*后缀表达式的计算*/
{
charc;
numstacknumst;/*建立数值栈*/
doubled1,d2,dr;
intk=0;/*后缀表达式的索引*/
inti=0;/*将字符转化为浮点数的索引*/
char*s;
chartrans[100];/*存字符表示的一段数字*/
init2(&numst);/*实现数值栈*/
c=exp[k++];
while(c!
='\0')/*开始扫描后缀表达式*/
{
if(c=='+'||c=='-'||c=='*'||c=='/'||c=='%')/*如果是操作符*/
{
switch(c)
{
case'+':
/*如果是加法操作*/
d2=pop2(&numst);
d1=pop2(&numst);
dr=d1+d2;/*相加后入栈*/
push2(&numst,dr);
break;
case'-':
/*如果是减法操作*/
d2=pop2(&numst);
d1=pop2(&numst);
dr=d1-d2;/*相减后入栈*/
push2(&numst,dr);
break;
case'*':
/*如果是乘法操作*/
d2=pop2(&numst);
d1=pop2(&numst);
dr=d1*d2;/*相乘后入栈*/
push2(&numst,dr);
break;
case'/':
/*如果是除法操作*/
d2=pop2(&numst);
d1=pop2(&numst);
dr=d1/d2;/*相除后入栈*/
push2(&numst,dr);
break;
case'%':
/*如果是取余操作*/
d2=pop2(&numst);
d1=pop2(&numst);
dr=(double)((int)d1%(int)d2);/*类型转化并取余后入栈*/
push2(&numst,dr);
break;
}
}
if(c>='0'&&c<='9'||c=='.')/*如果是字符表示的数字*/
{
while(c>='0'&&c<='9'||c=='.')
{
trans[i++]=c;/*将字符存入数组进行下一个的扫描*/
c=exp[k++];
}
trans[i++]='\0';/*将表示数字的字符串结束*/
i=0;
s=trans;/*将指针指向该数组*/
d1=atof(s);/*利用函数将字符串转化为浮点数*/
push2(&numst,d1);
}
c=exp[k++];
}
returnpop2(&numst);/*最后结果将在数值栈中,取出作为返回值*/
}
doubleDirectcalresult(charstr[])/*表达式的直接计算出结果*/
{
stackms;/*建立符号栈*/
numstackmns;/*建立数值栈*/
doublecalculate(doubleod1,doubleod2,OpNodeop);
intindex=0;/*str的索引*/
intlen=strlen(str);
charc;
chartrans[100];/*存放数值的一段字符*/
inti=0;/*trans的索引*/
char*s;
doubled;
OpNodetempn;/*存放当前扫描的操作符*/
OpNodetempln;
doubleoda,odb,odr;
doubleresult;/*作为返回值返回结果*/
init(&ms);/*实现两个栈*/
init2(&mns);
while(index { c=str[index++]; if(c>='0'&&c<='9'||c=='.')/*如果是数字字符或小数点*/ { while(c>='0'&&c<='9'||c=='.') { trans[i++]=c;/*将其存入数组扫描下一个*/ c=str[index++]; } trans[i++]='\0';/*扫描完一个数结束数组*/ i=0;/*索引归0*/ s=trans; d=atof(s); push2(&mns,d);/*转化为浮点数入栈*/ } if(c=='+'||c=='-')/*如果是+-*/ { tempn.level=1;/*优先级设为1*/ tempn.op=c; if(ms.size==0) { push(&ms,tempn);/*栈为空直接入栈*/ } else { templn=top(&ms); while(templn.level>=tempn.level)/*栈顶优先级高*/ { templn=pop(&ms);/*取出操作数和操作符计算*/ odb=pop2(&mns); oda=pop2(&mns); odr=calculate(oda,odb,templn); push2(&mns,odr);/*结算结果入栈*/ if(ms.size>0) { templn=top(&ms);/*如果栈空结束*/ } else break; } push(&ms,tempn);/*操作符入栈*/ } } if(c=='*'||c=='/'||c=='%')/*如果是%操作*/ { tempn.level=2;/*定义优先级为2*/ tempn.op=c; if(ms.size==0) { push(&ms,tempn);/*栈空直接入栈*/ } else { templn=top(&ms); while(templn.level>=tempn.level)/*栈顶优先级高*/ { templn=pop(&ms);/*取出操作数和操作符计算*/ odb=pop2(&mns); oda=pop2(&mns); odr=calculate(oda,odb,templn); push2(&mns,odr);/*结算结果入栈*/ if(ms.size>0) { templn=top(&ms); } else break;/*如果栈空结束*/ templn=top(&ms); } push(&ms,tempn);/*操作符入栈*/ } } if(c=='(')/*如果是左括号*/ { tempn.level=-1; tempn.op=c;/*直接入栈优先级定位-1*/ push(&ms,tempn); } if(c==')')/*如果是右括号*/ { while(tempn.op! ='(')/*遇到左括号结束*/ { templn=pop(&ms); odb=pop2(&mns);/*从数栈中取两个数,从符号栈里取操作符*/ oda=pop2(&mns); odr=calculate(oda,odb,templn);/*计算出结果入栈*/ push2(&mns,odr); if(ms.size>0) tempn=top(&ms); else break;/*如果栈空结束*/ } pop(&ms);/*取出左括号*/ } } tempn=top(&ms); while (1) { templn=pop(&ms); odb=pop2(&mns);/*从数栈中取两个数,从符号栈里取操作符*/ oda=pop2(&mns); odr=calculate(oda,odb,templn);/*计算出结果入栈*/ push2(&mns,odr); if(ms.size>0) tempn=top(&ms);/*如果栈空结束*/ else break; } result=pop2(&mns);/*最后的结果在数值栈中返回*/ returnresult; } doublecalculate(doubleod1,doubleod2,OpNodeop)/*已知操作符和操作数的计算*/ { switch(op.op) { case'+': returnod1+od2; case'-': returnod1-od2;/*判断操作符是哪个执行相应计算*/ case'*': returnod1*od2; case'/': returnod1/od2; case'%': return(double)((int)od1%(int)od2); } return0;/*如果上面的都没有执行返回0*/ } intcheck(charstr[],charchestr[100])/*容错函数*/ { charc; charcdivide; inti=0;/*str的索引*/ stackche;/*括号匹配用到的栈*/ OpNodetemp; intk=0;/*chestr的索引*/ intisinteger(charinteger[100]);/*%计算是判断是否是整数*/ chars1[10];/*%操作时存储%左右的数字*/ chars2[10]; intindexs1=0;/*s1s2的索引*/ intindexs2=0; intj;/*数组chestr索引*/ intflag=0;/*0--没有出错1--有错*/ inttag=0; init(&che); c=str[i];/*开始扫描*/ for(j=0;j<99;j++) { chestr[j]='';/*数组初始化待以后加入'^'*/ } chestr[j]='\0'; while(c! ='\0') { if(c=='(')/*如果是左括号就入栈*/ { temp.op=c; push(&che,temp); } if(c==')')/*如果是右括号*/ { if(che.size>0) { pop(&che);/*栈不为空就取出一个左括号*/ } else { flag=1; printf("缺少左括号\n");/*否则提示有错*/ chestr[i]='^';/*右括号下加'^'*/ } } if(c=='/')/*判断除数是否为0*/ { j=0; cdivide=str[i+1+j];/*取出除号后的数*/ while(cdivide>='0'&&cdivide<='9'||cdivide=='.')/*如果是数或小数点就一直存*/ { s1[j++]=cdivide; if(cdivide! ='0'&&cdivide! ='.')/*如果不是0则正确并结束*/ { tag=1; break; } cdivide=str[i+j+1]; } if(! tag)/*如果tag为0则存在错误除数为0*/ { chestr[i+1]='^'; flag=1;/*flag为1表示有错*/ } } if(c=='%')/*取余操作的容错*/ { while(str[i-indexs1-1]>='0'&&str[i-indexs1-1]<='9' ||str[i-indexs1-1]=='.')/*以%为中心向前扫描*/ { s1[indexs1++]=str[i-indexs1-1];/*如果是数或小数点*/ }/*放在s1中*/ while(str[i+indexs2+1]>='0'&&str[i+indexs2+1]<='9'/*以%为中心向后扫描*/ ||str[i+indexs2+1]=='.') {/*如果是数或小数点*/ s2[indexs2++]=str[i+indexs2+1];/*放在s1中*/ } if(isinteger(s1))/*调用函数判断s1内存到是否是整数*/ { printf("取余算法第一个数应为整数运算\n"); flag=1;/*记录为有错*/ chestr[i-indexs1]='^'; } if(isinteger(s2))/*调用函数判断s2内存到是否是整数*/ { printf("取余算法第二个数应为整数运算\n"); flag=1;/*记录为有错*/ chestr[i+indexs2]='^'; } } i++; c=str[i];/*检索下一个字符*/
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验五 中缀表达式转化为后缀表达式算法昆工版本 实验 中缀 表达式 转化 后缀 算法 版本