算术表达式求值系统.docx
- 文档编号:28814055
- 上传时间:2023-07-19
- 格式:DOCX
- 页数:19
- 大小:141.95KB
算术表达式求值系统.docx
《算术表达式求值系统.docx》由会员分享,可在线阅读,更多相关《算术表达式求值系统.docx(19页珍藏版)》请在冰豆网上搜索。
算术表达式求值系统
数据结构课程设计报告
课设题目:
算式表达式求值系统
班级:
软件1202
姓名:
学号:
***** **
成绩:
2013年1月
一、需求分析.......................................2
二、概要设计.......................................2
(一)设计思想......................................2
(二)实现方法......................................2
(三)模块整体设计图................................3
(四)函数功能介绍..................................3
三、详细设计.......................................4
(一)数据结构设计.................................4
(二)模块接口设计.................................4
(三)盒图.........................................5
四、调试分析.......................................7
五、用户手册.......................................7
六、测试结果.......................................8
七、附录...........................................9
附录一设计体会....................................9
附录二源程序......................................9
一、需求分析
算式表达式求值是程序设计语言编译中一个最基本的问题。
本次任务要求完成一个四则算式表达式求值系统。
具体需求为:
当用户输入一个四则算式(包括加、减、乘、除和括号),如(12+3)*2+9*4,输出其计算结果。
具体要求如下:
(一)要实现栈的基本操作算法,包括初始化栈、进栈、出栈等。
(二)在本程序中,表达式中的元素限定为char型,表达式长度不超过100,表达式以“#”号为结束标志。
(三)要求程序输出表达式的计算结果。
二、概要设计
(一)设计思想
本次四则算式表达式求值的程序采用的是中缀表达式的求值的方法。
所谓中缀表达式,就是指每个二目运算符在两个运算量的中间,假设所讨论的算术运算符包括:
+、-、*、/、%、^(乘方)和括号()。
而本次程序的编写只涉及四则运算(+、-、*、/)和括号()。
设运算规则为:
.运算符的优先级为:
()>*、/> +、- ;
.有括号出现时先算括号内的,后算括号外的,多层括号,由内向外进行;
表达式作为一个满足表达式语法规则的串存储,如表达式“3*2^(4+2*2-1*3)-5”,它的的求值过程为:
自左向右扫描表达式,当扫描到3*2时不能马上计算,因为后面可能还有更高的运算,正确的处理过程是:
需要两个栈:
对象栈s1和算符栈s2。
当自左至右扫描表达式的每一个字符时,若当前字符是运算对象,入对象栈,是运算符时,若这个运算符比栈顶运算符高则入栈,继续向后处理,若这个运算符比栈顶运算符低则从对象栈出栈两个运算量,从算符栈出栈一个运算符进行运算,并将其运算结果入对象栈,继续处理当前字符,直到遇到结束符“#”。
根据运算规则,左括号“(”在栈外时它的级别最高,而进栈后它的级别则最低了;乘方运算的结合性是自右向左,所以,它的栈外级别高于栈内;就是说有的运算符栈内栈外的级别是不同的。
当遇到右括号“)”时,一直需要对运算符栈出栈,并且做相应的运算,直到遇到栈顶为左括号“(”时,将其出栈,因此右括号“)”级别最低但它是不入栈的。
对象栈初始化为空。
根据以上分析,每个运算符栈内、栈外的级别如下:
算符栈内级别栈外级别
^34
*、/、%22
+、-11
(04
)-1-1
(二)实现方法
由于算符是字符类型,而表达式中的数字为数值类型,如果建立两个栈的结构的话,他们除了数据元素不同,其余操作都是类似的,这样不仅会增加程序的空间开销和执行时间,而且也使程序冗余度较大。
我采用的解决方案是设置一个算符值x来表示算符,+、-、*、/、(、)的算符值依次为:
1,2,3,4,5,6,用一个switch-case语句将算符转化为相应的数值,然后再入栈,这样就统一了对象栈和算符栈元素的数据类型。
在将“(”出栈时,要避免将初值0数据多次入栈而导致出错,如2*(3-1)-1,正常情况下在遇到*时,就应该将数字2入对象栈,然后将保存算式中数值的变量a置零,但是当遇到“(”时,又要将数字0入栈,这样就会导致结果出错,所以在用户输入的数据入对象栈之前,应先判断是否为“(”,若为“(”,则不能将数据入对象栈;当遇到“)”时,“(”不能入栈,并且要将前面的“3”,“-”,“1”都依次出栈进行计算,在遇到“(”时,将“(”出栈,但接下来又会遇到“-”,因此又要将数字0入栈,这样也会导致结果出错因此,我用了一个z[Max]数组来存放“(”的算符值,在每次入对象栈之前,都需要判断在z[i-1]的值。
在解决了数据类型问题之后,程序的编写就显得容易多了。
基本的操作包括栈的初始化、入栈、出栈、判空栈以及取栈顶元素,然后按照设计思路编写求四则表达式值的程序,此外还有一个界面程序,通过调用清屏函数system("cls")以及switch-case语句来实现界面的切换。
(三)模块整体设计图
算式表达式求值系统
(四)函数功能介绍
1.主函数voidmain()
功能:
调用其他各个函数;
2.菜单函数intmenu()
功能:
构造系统界面;
3.算式求值函数voidsuanshi()
功能:
求解四则算式表达式之值
4.栈初始化函数SeqStack*Init_SeqStack()
功能:
置空栈
5.入栈函数intPush_SeqStack(SeqStack*s,intx)
功能:
将数据元素入栈
6.出栈函数intPop_SeqStack(SeqStack*s,int*x)
功能:
将数据元素出栈
7.取栈顶元素函数intTop_SeqStack(SeqStack*s)
功能:
取出栈顶元素并将栈顶指针减一
8.判空栈函数intEmpty_SeqStack(SeqStack*s)
功能:
判断是否为空栈
三、详细设计
(一)数据结构设计
1.本系统采用结构体来定义栈,其结构如下:
typedefstruct
{
intdata[Max];
inttop;
}SeqStack;
并且设置了两个栈s1,s2分别表示对象栈和算符栈。
2.定义了一个z[Max]数组用来存放出栈的“(”的算符值,以避免将数据初值0入栈而导致出错。
(二)模块接口设计:
1.各函数原型为:
voidmain()/*主函数*/
intmenu()/*菜单函数*/
voidsuanshi()/*计算四则运算表达式*/
SeqStack*Init_SeqStack()/*栈初始化*/
intPush_SeqStack(SeqStack*s,intx)/*入栈*/
intPop_SeqStack(SeqStack*s,int*x)/*出栈*/
intTop_SeqStack(SeqStack*s)/*取栈顶元素*/
intEmpty_SeqStack(SeqStack*s)/*判断是否为空栈*/
2.系统界面切换的实现
利用清屏函数system("cls")实现屏幕切换,在从本界面返回上一界面时,根据提示输入即可,例如:
printf("是否继续查询,输入y或Y继续,输入其他键返回上一菜单\n");
scanf("%c",&choice);
if(choice=='y'||choice=='Y')suanshi();
则输入输入任意键都能返回上一界面,在main()函数中用for的无穷循环语句实现各函数的循环调用,以使各功能能够重复实现,直至用户退出系统为止。
(三)盒图:
1.主函数盒图
图2主函数盒图
2.菜单函数盒图
图3菜单函数盒图
3.算术求值函数盒图
图4算术求值函数盒图
4.入栈函数盒图
图5入栈函数盒图
\\
\\_
.---(')
o()_-\_
\\
\\_
.---(')
o()_-\_
四、调试分析
在调试过程中我遇到的问题以及我的采取措施有:
(一)我先编写只含有加减的运算表达式,然后把乘除加进来,最后再把括号加进来。
因为加减的优先级相同,所以一刚开始,我并没有用栈来做,而是用数组来做,我设置了一个整数类型的数组用来保存表达式中的数值,一个字符类型的数组用来保存算符,然后从左往右依次计算即可,因此,没有什么大问题。
在将乘除加进来的时候,由于涉及到优先级的问题,因此,我不得不将对象数组和算符数组转换为对象栈和算符栈。
当我把括号加进来的时候,就遇到了将初值0数据多次入栈而导致出错的现象,所以,我设置了一个z[Max]数组用来存放“(”出栈时的值,从而解决了问题。
(二)在接收用户输入的数据的时候,我用了整型数据来接收,这样在做除法运算的时候,就有可能会出现运算结果与预期结果不相符的情况,比如1/2,在本系统中运行的结果为0,但是我们预期的结果应该是0.5。
但是如果将栈中的数据元素定义为实型,当将出栈的元素放入switch-case语句中时,系统又会报错。
由于时间原因,我并没有对此做修改,还是将栈中的数据元素定义为整型,但是这样可能会导致在做除法运算的时候,出现结果不准确的情况,这也是本系统的一个漏洞。
(注:
本系统的所有代码都是在windows环境下的MicrosoftVisualC++6.0编译器中运行的。
)
五、用户手册
(一)进入系统
双击算术表达式求值系统.cpp文件,按compile键(或Ctrl+F5)编译程序,再按BuildExecute键(或Ctrl+F5)运行程序,然后就进入了算术表达式求值系统;也可以直接在Debug中找到算术表达式求值系统.exe文件,然后双击它,直接进入系统。
(二)求表达式之值
1.进入系统后,输入“1”,按回车,即进入算式表达式求值界面,若输入了除“1”和“2”以外的其他键,则会出现输入错误的提示信息,再按一次回车将重新回到菜单界面。
2.输入一个表达式以“#”为结束标志,要求输入的所有数据都为整数,且只能输入四则运算的算式,即算式中只含有+、-、*、/以及括号,如输入(12+3)*2+9*4#,按回车,即能得到结果。
3.如果想继续进行计算,则可以输入“y”或“Y”,然后重复步骤2,输入其他键将返回上一菜单。
(三)退出系统
当回到菜单界面时,输入“2”,将会出现退出系统的提示信息,然后按任意键退出算术表达式求值系统。
六、测试结果
(一)菜单界面
图6菜单界面截图
(二)求值界面
图7求值界面截图
(三)报错界面
图8报错界面截图
(四)退出界面
图9退出界面截图
七、附录
附录一设计体会
本次课程设计难度不是很大,因为在平时做实验的时候有类似的题目,而且老师也有讲过中缀表达式的思想,只是要将其变成一个系统而已。
本次程序设计的关键在于理解中缀表达式算法的基本思想,然后用栈的方法来解决问题。
其中要考虑到“)”,“)”不能入栈,且“)”后面又是一个运算符,因此不能将此时存储数据元素的a=0入栈,否则会出现错误,还有要注意“(”何时出栈等问题。
由于课程设计这一周我们有许多考试,所以时间有些紧迫,设计程序的时候有些仓促,因此本系统还存在一些不足之处以及可改进的地方。
下面就本系统的特色及不足之处作简要说明:
(一)系统特色
1.采用菜单的方式工作,简洁明了,易于操作。
2.系统界面较为人性化,有提示输入的信息和错误提示,便于用户输入。
3.能够实现带括号的整数四则运算,并将结果显示在屏幕上。
(二)系统进一步扩充
1.界面美化程度还有待提高。
2.在进入每一个子界面后,只能逐级返回,而不能一下子退出系统。
3.只能计算整数类型的数据,而且在使用整型数据的时候,在做除法运算时,就有可能会出现运算结果与预期结果不相符的情况,比如1/2,在本系统中运行的结果为0,但是我们预期的结果应该是0.5,这样会给用户带来很大不便。
附录二源程序
#include
#include
#include
#defineMax100
typedefstruct/*定义栈的结构*/
{
intdata[Max];
inttop;
}SeqStack;
SeqStack*Init_SeqStack()/*栈初始化*/
{
SeqStack*s;
s=(SeqStack*)malloc(sizeof(SeqStack));
s->top=-1;
returns;
}
intEmpty_SeqStack(SeqStack*s)/*判断是否为空栈*/
{
if(s->top==-1)return1;
elsereturn0;
}
intPush_SeqStack(SeqStack*s,intx)
{/*入栈*/
if(s->top==Max-1)return0;/*栈满不能入栈*/
else
{
s->top++;
s->data[s->top]=x;
return1;
}
}
intPop_SeqStack(SeqStack*s,int*x)
{/*出栈*/
if(Empty_SeqStack(s))return0;/*栈空不能出栈*/
else
{*x=s->data[s->top];
s->top--;return1;/*栈顶元素存入*x,返回*/
}
}
intTop_SeqStack(SeqStack*s)
{/*取栈顶元素*/
if(Empty_SeqStack(s))return0;/*栈空*/
elsereturn(s->data[s->top]);
}
voidsuanshi()/*计算四则运算表达式*/
{
system("cls");/*清屏函数*/
charchoice,a1[Max],*p;
printf("请输入一个带有括号的四则运算的算式以#结束:
\n");
scanf("%s",a1);
SeqStack*s1,*s2;
p=a1;
charc=*p++;
intsum,result,a=0,b,d,e1=0,e2,f,x,y,z[Max]={0},i=1;
s1=Init_SeqStack();/*对象栈*/
s2=Init_SeqStack();/*算符栈*/
while(c)
{
if(c>='0'&&c<='9')a=a*10+c-'0';/*将字符串数字转化为数值*/
else
{
switch(c)/*将运算符数据化存入栈中并设栈内栈外优先级*/
{
case'#':
x=0;e2=-1;f=-1;break;
case'+':
x=1;e2=1;f=1;break;
case'-':
x=2;e2=1;f=1;break;
case'*':
x=3;e2=2;f=2;break;
case'/':
x=4;e2=2;f=2;break;
case'(':
x=5;e2=0;f=4;break;
case')':
x=6;e2=-1;f=-1;break;
}
if(x!
=5&&z[i-1]==0)/*将数值入对象栈*/
{
Push_SeqStack(s1,a);
a=0;
}
i++;
if(Empty_SeqStack(s2)||e1 { Push_SeqStack(s2,x); e1=e2;/*修改优先级*/ } else { while(e1>=f) { Pop_SeqStack(s2,&y);/*取出两个数据和一个运算符*/ Pop_SeqStack(s1,&b); Pop_SeqStack(s1,&d); switch(y)/*判断为何种运算符并做计算*/ { case1: sum=b+d;break; case2: sum=d-b;break; case3: sum=b*d;break; case4: sum=d/b;break; case5: Pop_SeqStack(s2,&z[i++]);break; } Push_SeqStack(s1,sum);/*中间结果入对象栈*/ if(Empty_SeqStack(s2))break; else { y=Top_SeqStack(s2); if(x==6&&y==5)/*如果遇到“)”和“(”*/ { Pop_SeqStack(s2,&z[i++]); break; } else { switch(y)/*修改优先级*/ { case1: case2: e2=1;break; case3: case4: e2=2;break; case5: e2=0;break; } e1=e2; } } } if(x! =6&&x! =0)/*如果没有遇到“)”*/ { Push_SeqStack(s2,x); switch(x) { case1: case2: e2=1;f=1;break; case3: case4: e2=2;f=2;break; case5: e2=0;f=4;break; } e1=e2; } } } c=*p++; } Pop_SeqStack(s1,&result);/*将最终结果出栈*/ printf("结果为: %d\n",result);/*在屏幕上显示最终结果*/ getchar(); printf("是否继续进行计算,输入y或Y继续,输入其他键返回上一菜单\n"); scanf("%c",&choice); if(choice=='y'||choice=='Y')suanshi(); } intmenu()/*菜单函数*/ { system("cls"); intx; printf("\n"); printf("*************************欢迎进入算术表达式求值系统*************************\n"); printf("1.算术表达式求值\n"); printf("2.退出系统\n"); printf("请输入您想选择的操作: (1-2)\n"); scanf("%d",&x); returnx; } voidmain()/*主函数*/ { intc,i;/*变量c为用户的选择*/ for(i=0;;i++)/*变量i为循环次数*/ { c=menu(); switch(c) { case1: suanshi();break; case2: { printf("**********************************正在退出**********************************\n"); printf("********************************欢迎下次使用********************************\n"); exit(0); } default: { printf("输入菜单号有误,请重新输入,按回车键结束! \n"); getchar(); getchar(); } } } }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 算术 表达式 求值 系统