中缀算术表达式求值.docx
《中缀算术表达式求值.docx》由会员分享,可在线阅读,更多相关《中缀算术表达式求值.docx(17页珍藏版)》请在冰豆网上搜索。
![中缀算术表达式求值.docx](https://file1.bdocx.com/fileroot1/2022-12/13/feed0713-e0d5-46f0-b96a-0f64d1218793/feed0713-e0d5-46f0-b96a-0f64d12187931.gif)
中缀算术表达式求值
目录
一、设计内容1
二、概要设计1
1.程序的功能。
1
2.输入输出的要求1
3.程序构成:
1
4.数据结构及存储方式2
三、详细设计2
1.采用C语言定义相关的数据类型。
2
2.写出各模块的类C码算法。
3
3.各函数的调用关系图。
8
四、调试分析以及设计体会9
1.测试数据:
9
2.程序调试中遇到的问题以及解决问题的方法:
9
3.课程设计过程经验教训、心得体会10
五、附录11
六、评分表16
一、设计内容
课题一:
中缀算术表达式求值
我们很早就学习如何书写及计算表达式,诸如:
8+5*(7-3)之类的表达式,先算括号内的7减去3,得到4,然后再算5乘以4,得到20,再计算8加上20,得到28,因此该表达式的值为28。
这是人们熟悉的运算规则额:
有括号先算括号内;无括号时,先做乘除法,后做加减法;对于相同级别的运算按从左到右的次序运算。
而计算机是如何实现表达式的计算的呢?
应用栈的相关知识,编程序实现之。
设计思路:
从键盘输入中缀表达式,然后将中缀表达式转换为后缀表达式,利用后缀表达式求值。
要求以字符序列的形式从终端输入语法正确的、不含变量的整数表达式,利用给定的算术符优先关系,实现对算数四则混合运算表达式的求值,并演示在求值过程中运算符栈、操作符栈、输入字符和主要操作的变化过程。
二、概要设计
1.程序的功能
该程序能够对任意的四则运算表达式进行中缀表达式向后缀表达式的转换,并得出其计算结果。
2.输入输出的要求
输入输出均是阿拉伯数字和四则运算操作符以及括号运算符,按照程序所给提示进行标准输入输出即可。
3.程序构成
1)StackInit函数,主要用来实现函数的初始化;
2)StackPush函数,主要用来执行入栈操作,为实现中缀转后缀提供可能;
3)StackPop函数,主要用来执行出栈操作,为转换函数所应用;
4)StackTop函数,主要用来执行取栈顶元素操作,为转换表达式做准备;
5)Compare函数,主要用来实现比较运算符的优先级别的比较,为后面的函数转换做准备;
6)Transfer函数,主要用来实现中缀表达式转换成为后缀表达式,为后面的计算提供条件;
7)Calculate函数,主要用来综合前面函数的结果,从而计算出表达式的值;
8)main函数,主要用来实现数据的输入输出以及测试;
各个函数之间均有其内在的数据以及结构上的联系,在main函数里面调用了Transfer函数和Calculate函数,而在Transfer函数内部,有调用了之前的StackInit函数、StackPush函数、StackTop函数以及Compare函数和StackPop函数。
4.数据结构及存储方式
该课题程序主要涉及了栈的数据结构,其存储的字符型和整型。
如:
typedefstructstack
{
Elemtypedata;
structstack*next;
}Sqstack;
三、详细设计
1.采用C语言定义相关的数据类型
定义栈:
typedefstructstack
{
Elemtypedata;
structstack*next;
}Sqstack;
2.写出各模块的类C码算法
1)初始化函数
voidStackInit(Sqstack**head)
{
if((*head=(Sqstack*)malloc(sizeof(Sqstack)))==NULL)exit
(1);
(*head)->next=NULL;
}
2)入栈
intStackPush(Sqstack*head,Elemtypex)
{
Sqstack*p;
if((p=(Sqstack*)malloc(sizeof(Sqstack)))==NULL)
{
printf("内存空间不足无法插入");
return0;
}
p->data=x;
p->next=head->next;
head->next=p;
return1;
}
3)出栈
intStackPop(Sqstack*head,Elemtype*d)
{
Sqstack*p=head->next;
if(p==NULL)
{
printf("堆栈已空出错!
");
return0;
}
head->next=p->next;
*d=p->data;
free(p);
return1;
}
4)取栈顶元素
intStackTop(Sqstack*head,Elemtype*d)
{
Sqstack*p=head->next;
if(p==NULL)
{
printf("堆栈已空出错!
");
return0;
}
*d=p->data;
return1;
}
5)比较操作符优先级
intCompare(chara,charb)
{
if((a=='+'||a=='-')&&(b=='*'||b=='/'||b=='('))
return'<';
elseif((a=='*'||a=='/')&&b=='(')
return'<';
elseif(a=='('&&(b=='+'||b=='-'||b=='*'||b=='/'||b=='('))
return'<';
elseif(a=='('&&b==')')
return'=';
elseif(a=='#'&&(b=='+'||b=='-'||b=='*'||b=='/'||b=='('))
return'<';
elseif(a=='#'&&b=='#')
return'=';
else
return'>';
}
6)中缀变后缀
intTransfer(charExpression[],intn,charsave[])
{
Sqstack*s;
charx1,x2,y;
inti;
intj=0;
StackInit(&s);
StackPush(s,'#');
for(i=0;i{
x1=Expression[i];
if(x1<='9'&&x1>='0')
{
save[j]=x1;
j++;
y=Expression[i+1];
if(y=='+'||y=='-'||y=='*'||y=='/'||y=='('||y==')'||y=='#')
{
save[j]='';
j++;
}
}
else
{
StackTop(s,&x2);
if(Compare(x2,x1)=='<')
StackPush(s,x1);
elseif(Compare(x2,x1)=='>')
{
StackPop(s,&x2);
save[j]=x2;
j++;
i--;
}
elseif(Compare(x2,x1)=='=')StackPop(s,&x2);
}
}
save[j]='#';
returnj;
}
7)后缀表达式求值
voidCalculate(charp[])
{
ints[100];
inti,j;
i=j=0;
while(p[j]!
='#')
{
switch(p[j])
{case'+':
s[i-2]=s[i-2]+s[i-1];
i=i-1;
break;
case'-':
s[i-2]=s[i-2]-s[i-1];
i=i-1;
break;
case'*':
s[i-2]=s[i-2]*s[i-1];
i=i-1;
break;
case'/':
s[i-2]=s[i-2]/s[i-1];
i=i-1;
break;
case'0':
case'1':
case'2':
case'3':
case'4':
case'5':
case'6':
case'7':
case'8':
case'9':
s[i]=(int)p[j]-48;
j++;
while(p[j]!
='')
{
s[i]=s[i]*10+(int)p[j]-48;
j++;
}
i++;
break;
}
j++;
}
8)主函数
voidmain()
{
intm;
inti=0;
intk;
charsave[100];
chara[100];
printf("输入字符串,并以#号结束\n");
for(m=0;m<100;m++)
{
scanf("%c",&a[m]);
if(a[m]=='#')break;
}
Transfer(a,m+1,save);
k=Transfer(a,m+1,save);
printf("后缀表达式为:
");
for(m=0;mprintf("%c",save[m]);
Calculate(save);
printf("\n");
}
3.各函数的调用关系图
图一、各个函数调用关系图
四、调试分析以及设计体会
1.测试数据:
如输入表达式(56-20)/(4+2)#
图二、输入界面
得到的结果为
图三、输出界面
2.程序调试中遇到的问题以及解决问题的方法:
1)在调试中,由于粗心,误把Calculate函数里面的数据结果输出的格式写成了%s,而实际应该是%d,所以编译的时候没出现问题,在运行的时候却输不出结果,如下面所示
图四、错误输出结果
最后改过来才能够得出输出的计算结果。
2)在编程序的时候,误把Transfer函数在主函数里面的调用写成了transfer,所以在编译的时候报错:
图五、程序报错显示
将其改过来才得到正确结果。
3.课程设计过程经验教训、心得体会。
本次课程设计,使我对《数据结构》这门课程有了更深入的理解.《数据结构》是一门实践性较强的课程,为了学好这门课程,必须在掌握理论知识的同时,加强上机实践.一个人的力量是有限的,要想把课程设计做的更好,就要学会参考一定的资料,吸取别人的经验,让自己和别人的思想有机的结合起来,得出属于你自己的灵感.
在本课程设计中,我明白了理论与实际应用相结合的重要性,并提高了自己组织数据及编写大型程序的能力.培养了基本的,良好的程序设计技能以及合作能力.这次课程设计同样提高了我的综合运用所学知识的能力.程序的编写需要有耐心,有些事情看起来很复杂,但问题需要一点一点去解决,分析问题,把问题一个一个划分,划分成小块以后就逐个去解决.再总体解决大的问题.这样做起来不仅有条理也使问题得到了轻松的解决.
通过这段时间的课程设计,我认识到数据结构是一门比较难的课程.需要多花时间上机练习.这次的程序训练培养了我实际分析问题,编程和动手能力,使我掌握了程序设计的基本技能,提高了我适应实际,实践编程的能力.
这次的课程设计我对于专业课的学习有了更加深刻的认识,以为现在学的知识用不上就加以怠慢,等到想用的时候却发现自己的学习原来是那么的不扎实.以后努力学好每门专业课,让自己拥有更多的知识,才能解决更多的问题!
总的来说,这次课程设计让我获益匪浅,对数据结构也有了进一步的理解和认识
五、附录
程序源代码:
#include"stdio.h"
#include"stdlib.h"
typedefcharElemtype;
typedefstructstack
{
Elemtypedata;
structstack*next;
}Sqstack;
voidStackInit(Sqstack**head)//初始化
{
if((*head=(Sqstack*)malloc(sizeof(Sqstack)))==NULL)exit
(1);
(*head)->next=NULL;
}
intStackPush(Sqstack*head,Elemtypex)//入栈
{
Sqstack*p;
if((p=(Sqstack*)malloc(sizeof(Sqstack)))==NULL)
{
printf("内存空间不足无法插入");
return0;
}
p->data=x;
p->next=head->next;
head->next=p;
return1;
}
intStackPop(Sqstack*head,Elemtype*d)//出栈
{
Sqstack*p=head->next;
if(p==NULL)
{
printf("堆栈已空出错!
");
return0;
}
head->next=p->next;
*d=p->data;
free(p);
return1;
}
intStackTop(Sqstack*head,Elemtype*d)//取栈顶元素
{
Sqstack*p=head->next;
if(p==NULL)
{
printf("堆栈已空出错!
");
return0;
}
*d=p->data;
return1;
}
intCompare(chara,charb)//比较操作符优先级
{
if((a=='+'||a=='-')&&(b=='*'||b=='/'||b=='('))
return'<';
elseif((a=='*'||a=='/')&&b=='(')
return'<';
elseif(a=='('&&(b=='+'||b=='-'||b=='*'||b=='/'||b=='('))
return'<';
elseif(a=='('&&b==')')
return'=';
elseif(a=='#'&&(b=='+'||b=='-'||b=='*'||b=='/'||b=='('))
return'<';
elseif(a=='#'&&b=='#')
return'=';
else
return'>';
}
intTransfer(charExpression[],intn,charsave[])//中缀变后缀
{
Sqstack*s;
charx1,x2,y;
inti;
intj=0;
StackInit(&s);
StackPush(s,'#');
for(i=0;i{
x1=Expression[i];
if(x1<='9'&&x1>='0')
{
save[j]=x1;
j++;
y=Expression[i+1];
if(y=='+'||y=='-'||y=='*'||y=='/'||y=='('||y==')'||y=='#')
{
save[j]='';//在数字后面,操作符前面加空格
j++;
}
}
else
{
StackTop(s,&x2);
if(Compare(x2,x1)=='<')
StackPush(s,x1);
elseif(Compare(x2,x1)=='>')
{
StackPop(s,&x2);
save[j]=x2;
j++;
i--;
}
elseif(Compare(x2,x1)=='=')StackPop(s,&x2);
}
}
save[j]='#';//后缀表达式以'#'号结束
returnj;
}
voidCalculate(charp[])//后缀表达式求值
{
ints[100];
inti,j;
i=j=0;
while(p[j]!
='#')//
{
switch(p[j])
{case'+':
//将操作符前面的两个数值相加
s[i-2]=s[i-2]+s[i-1];
i=i-1;
break;
case'-':
//将操作符前面的两个数值相减
s[i-2]=s[i-2]-s[i-1];
i=i-1;
break;
case'*':
//将操作符前面的两个数值相乘
s[i-2]=s[i-2]*s[i-1];
i=i-1;
break;
case'/':
//将操作符前面的两个数值相除
s[i-2]=s[i-2]/s[i-1];
i=i-1;
break;
case'0':
//如果扫描到的是字符0~9,执行下面操作
case'1':
case'2':
case'3':
case'4':
case'5':
case'6':
case'7':
case'8':
case'9':
s[i]=(int)p[j]-48;//48是0的ASCII码值,将数字字符char型向int类型转换
j++;
while(p[j]!
='')//判断一个操作数是否结束,每个操作数都是以空格结束
{
s[i]=s[i]*10+(int)p[j]-48;//求出数字字符的值
j++;
}
i++;
break;
}
j++;
}printf("\n计算的结果为:
%d",s[0]);
}
voidmain()
{
intm;
inti=0;
intk;
charsave[100];
chara[100];
printf("输入字符串,并以#号结束\n");
for(m=0;m<100;m++)
{
scanf("%c",&a[m]);
if(a[m]=='#')break;
}
Transfer(a,m+1,save);
k=Transfer(a,m+1,save);
printf("后缀表达式为:
");
for(m=0;mprintf("%c",save[m]);
Calculate(save);
printf("\n");
}
六、评分表
计算机与通信学院课程设计评分表
课程名称:
中缀算术表达式求值
项目
评价
设计方案的合理性与创造性
设计与调试结果
设计说明书的质量
答辩陈述与回答问题情况
课程设计周表现情况
综合成绩
教师签名:
日期:
(注:
1.此页附在课程设计报告之后;2.综合成绩按优、良、中、及格和不及格五级评定。
)