算是表达式栈实验报告.docx
《算是表达式栈实验报告.docx》由会员分享,可在线阅读,更多相关《算是表达式栈实验报告.docx(16页珍藏版)》请在冰豆网上搜索。
算是表达式栈实验报告
中南大学
《数据结构与算法》课程实验
实验报告
题目线性表的操作
学生姓名张悦
学生学号3901090516
专业班级软件工程0905班
实验二栈的基本操作
一、实验目的
熟练掌握栈的基本操作:
初始化栈、判栈为空、出栈、入栈等运算。
理解栈在数据处理中扮演的角色,运用栈结构实现具体的应用。
二、实验内容
栈是数据结构中一个非常重要的结构。
表达式计算是掌握程序设计语言的重要部分之一,也是栈的应用的一个典型例子。
本次实验的主要内容是利用栈的基本操作,设计一个程序,实现用算符优先法对算术表达式求值的过程。
对本设计系统实现+、-、*、/、%和乘方(^)运算。
符合要求,同时提高自己的编程能力。
实现算术表达式求值。
选作内容:
提供对小数点的支持,允许输入的表达式中出现多位数字和小数点。
三、实验要求
1.认真阅读和掌握本实验的算法。
2.上机将本算法实现。
3.在程序的编写中尽量与专业的编程规范靠拢,系统代码采用结构化的编程方式,力求设计代码以及注释等规范,
4.保存和打印出程序的运行结果,并结合程序进行分析。
一.需求分析
本程序用于计算“+”、“-”、“*”、“\”、“^”、“()”的简单计算器,对简单的计算式子进行计算,并输出运算结果。
1.输入的形式和输入值的范围:
整数类型的实数(float),并以“#”对每个式子结尾;
2.输出的形式:
算式的最后结果;
3.程序所能达到的功能:
计算出所输入运算式子的结果;
4.测试数据:
①正确输入:
(3+4)*5#
输出结果:
35
②错误输入:
没有以“#”结尾、除数为0、输入了除“+”、“-”、“*”、“\”、“^”、“()”意外的运算符、括号的左右不匹配、数据溢出等。
输出结果:
“Operatorerror!
”、“Dividezero!
”、“Inputerror,Retry!
”、“Outofspace!
”
二.概要设计
栈的储存结构:
此方法中用到的抽象数据类型为结构体:
structSTACK1{//此为操作符的栈;
charsta[MAX];
inttop;
};
typedefstructSTACK1stack1;
structSTACK2{//此为运算数的栈;
floatsta[MAX];
inttop;
};
typedefstructSTACK2stack2;
主程序中提示输入所需要计算的运算公式,调用check_ch函数检查输入是否错误,然后调用operate函数计算所输入算式的计算所得结果;其中在operate函数中还调用了pop、push、Output等函数对所输入的运算公式进行计算。
最后用在主函数中直接输出经过operate函数计算后的程序结果。
三.详细设计
定义的栈的结构体:
structSTACK1{//储存运算符的栈
charsta[MAX];//定义存入运算符为char类型数据
inttop;
};
structSTACK2{//储存数字的栈
floatsta[MAX];//定义存入数字为float类型数据
inttop;
};
typedefstructSTACK1stack1;
typedefstructSTACK2stack2;
所用主要函数:
intcheck_ch(charch[MAX]){//查看表达式括号是否匹配函数
inti=0;
chartch;
stack1*s;
s=newstack1;
s->top=0;
while(ch[i]!
='#'){
switch(ch[i]){
case'(':
push(ch[i],s);break;
case')':
if(!
IsEmpty(s)){
tch=pop(s);
if(tch=='(')break;
elsereturn0;
}
else{
return0;
}
}
i++;
}
if(IsEmpty(s))
return1;
else
return0;
}
floatoperate(stack1*base,stack2*operand,charch[MAX]){//计算所给表达式的值
chartch;
inti=0;
push('#',base);//在栈低先压入"#"
while(ch[i]!
=NULL){
if(check(ch[i])){//对于运算表达式中的字符进行判断
floatNUM,num;
NUM=0;
while(check(ch[i])){
num=ch[i]-'0';
NUM=NUM*10+num;
i++;
}
push(NUM,operand);
}
else{
if(!
IsEmpty(base)){
if(ch[i]==')'){//遇到"("时的计算
tch=pop(base);
while(tch!
='('){
Output(tch,base,operand);
tch=pop(base);
}
}
else{
tch=base->sta[base->top];
while(Osp(ch[i])tch=pop(base);
Output(tch,base,operand);
tch=base->sta[base->top];
}
push(ch[i],base);
}
}
else{
push(ch[i],base);
}
i++;
}
}
tch=pop(base);
while(tch!
='#'){//把栈中剩余的运算符弹出进行计算
Output(tch,base,operand);
tch=pop(base);
}
returnpop(operand);//弹出栈中最后的数,即为运算式子的最后结果
}
intOutput(charch,stack1*base,stack2*operand){//弹出运算符时进行两数的运算
floatn1,n2,num;
n1=pop(operand);
n2=pop(operand);
num=analyse(n1,n2,ch);
push(num,operand);
return0;
}
主函数:
intmain(){
intflag;
while(flag){
charch[MAX],c;
stack1*base;
stack2*operand;
base=newstack1;
operand=newstack2;
floatnum;
if(base==NULL){
cout<<"Outofspace!
"<return-1;
}
if(operand==NULL){
cout<<"Outofspace!
"<return-1;
}
base->top=-1;
operand->top=-1;
cout<<"PleaseentertheExpressions,andendwith‘#’:
"<cin>>ch;
if(!
check_ch(ch)){
cout<<"puterror,Retry!
"<continue;
}
num=operate(base,operand,ch);
cout<<"Theansweris"<cout<<"Doyouwanttocontinue?
(y/n):
";
cin>>c;
if(c=='y'||c=='Y')//实现多次输入
flag=1;
else
flag=0;
deletebase;
deleteoperand;
}
return0;
}
函数和过程的调用关系图:
四.调试分析
在最一开始的时候,觉得栈是一个很神秘很抽象的东西,听老师讲课也觉得似懂非懂的,觉得理论上好像懂了,但遇到实际操作时,又开始糊涂了。
直到要开始做实验,对于栈的程序代码的编写才开始有了比较清晰的轮廓。
指针这方面我不太在行,所以我选择了用数组来进行栈的数据储存。
我觉得数和运算符应该分开,分别为两个栈,所以我用两个结构体分别定义了一个储存字符和数字。
为了能判断输入的数是否结束,我要求程序使用者在输入完算式后以“#”做结尾。
考虑到有些人会不注意输入的格式,或者是括号没有匹配等,借鉴了老师的程序,我用check_ch函数来判断输入的算式是否符合要求,如果不符合要求,则重新输入。
输入结束后,我就直接用了一个笼统的函数operate来对该算式来进行运算。
我对输入的字符串一个一个字符的进行操作。
当遇到数字时,用push函数压入数字栈内;当遇到符号时,分类讨论。
当符号为“)”时,开始放出符号栈中的栈顶符号,并进行运算,知道遇到符号“)”停止。
当遇到的是普通的符号时,比较符号栈的栈顶符号与该符号的优先级大小,优先级大的先进行运算。
运算是指在栈中弹出最后两个数与当前运算符进行运算,将得到的结果压入数字栈中。
当遇到“#”时,运算结束,弹出数字栈中最后的数,即为最终答案。
在实验过程中,一开始的程序是有错误的,主要是没有考虑到符号栈中当除去括号外多余的符号,而且“i++”这一句语句放错了位置,导致程序的结果永远是我输入的最后一位数字。
经过反复修改后,我的程序终于可以正常的运行了。
感谢老师提供的程序,让我解决了许多程序中无法正常运行的部分,并且我知道了如何输入多位数,让程序可以进行多位数的运算。
五.用户使用说明
运行程序后,会出现提示:
PleaseentertheExpressions,andendwith‘#’:
(输入运算式子,并以“#”结尾,按回车;例如输入:
(3+4)*5)
程序运行后,屏幕上会显示出:
Theansweris35.
Doyouwanttocontinue?
(y/n):
(输入Y或y,程序将继续进行计算,否则退出程序)
六.测试结果
七.附录
#include
usingnamespacestd;
constMAX=50;
structSTACK1{//储存运算符的栈
charsta[MAX];
inttop;
};
structSTACK2{//储存数字的栈
floatsta[MAX];
inttop;
};
typedefstructSTACK1stack1;
typedefstructSTACK2stack2;
floatoperate(stack1*base,stack2*operand,charch[MAX]);
intcheck(charch);
intIsp(charch);
intOsp(charch);
charpop(stack1*base);
floatpop(stack2*operand);
floatanalyse(floatn,floatm,charch);
floatpower(floatn,floatm);
intpush(floatnum,stack2*operand);
intpush(charch,stack1*base);
intIsEmpty(stack1*base);
intOutput(charch,stack1*base,stack2*operand);
intcheck_ch(charch[MAX]);
intmain(){
intflag;
while(flag){
charch[MAX],c;
stack1*base;
stack2*operand;
base=newstack1;
operand=newstack2;
floatnum;
if(base==NULL){
cout<<"Outofspace!
"<return-1;
}
if(operand==NULL){
cout<<"Outofspace!
"<return-1;
}
base->top=-1;
operand->top=-1;
cout<<"PleaseentertheExpressions,andendwith'#':
"<cin>>ch;
if(!
check_ch(ch)){
cout<<"puterror,Retry!
"<continue;
}
num=operate(base,operand,ch);
cout<<"Theansweris"<cout<<"Doyouwanttocontinue?
(y/n):
";
cin>>c;
if(c=='y'||c=='Y')//实现多次输入
flag=1;
else
flag=0;
deletebase;
deleteoperand;
}
return0;
}
intcheck_ch(charch[MAX]){//查看表达式括号是否匹配函数
inti=0;
chartch;
stack1*s;
s=newstack1;
s->top=0;
while(ch[i]!
='#'){
switch(ch[i]){
case'(':
push(ch[i],s);break;
case')':
if(!
IsEmpty(s)){
tch=pop(s);
if(tch=='(')break;
elsereturn0;
}
else{
return0;
}
}
i++;
}
if(IsEmpty(s))
return1;
else
return0;
}
floatoperate(stack1*base,stack2*operand,charch[MAX]){//计算所给表达式的值
chartch;
inti=0;
push('#',base);//在栈低先压入"#"
while(ch[i]!
=NULL){
if(check(ch[i])){//对于运算表达式中的字符进行判断
floatNUM,num;
NUM=0;
while(check(ch[i])){
num=ch[i]-'0';
NUM=NUM*10+num;
i++;
}
push(NUM,operand);
}
else{
if(!
IsEmpty(base)){
if(ch[i]==')'){//遇到"("时的计算
tch=pop(base);
while(tch!
='('){
Output(tch,base,operand);
tch=pop(base);
}
}
else{
tch=base->sta[base->top];
while(Osp(ch[i])tch=pop(base);
Output(tch,base,operand);
tch=base->sta[base->top];
}
push(ch[i],base);
}
}
else{
push(ch[i],base);
}
i++;
}
}
tch=pop(base);
while(tch!
='#'){//把栈中剩余的运算符弹出进行计算
Output(tch,base,operand);
tch=pop(base);
}
returnpop(operand);//弹出栈中最后的数,即为运算式子的最后结果
}
intOutput(charch,stack1*base,stack2*operand){//弹出运算符时进行两数的运算
floatn1,n2,num;
n1=pop(operand);
n2=pop(operand);
num=analyse(n1,n2,ch);
push(num,operand);
return0;
}
intIsEmpty(stack1*base){//判断栈是否为空
if(base->top==0)
return1;
else
return0;
}
intcheck(charch){//判断读入的字符是否为数字
if(ch<'0'||ch>'9')
return0;
else
return1;
}
intpush(floatnum,stack2*operand){//压入栈的操作
operand->top++;
if(operand->top>MAX){
cout<<"Outofspace!
"<return-1;
}
operand->sta[operand->top]=num;
return0;
}
intpush(charch,stack1*base){
base->top++;
if(base->top>MAX){
cout<<"Outofspace!
"<return-1;
}
base->sta[base->top]=ch;
return0;
}
charpop(stack1*base){//弹出栈的操作
chartch;
tch=base->sta[base->top];
base->top--;
returntch;
}
floatpop(stack2*operand){
floattnum;
tnum=operand->sta[operand->top];
operand->top--;
returntnum;
}
intIsp(charch){//运算符优先级的判断
switch(ch){
case'#':
return0;break;
case'(':
return1;break;
case'+':
return3;break;
case'-':
return3;break;
case'*':
return5;break;
case'/':
return5;break;
case'^':
return7;break;
case')':
return8;break;
}
}
intOsp(charch){
switch(ch){
case'#':
return0;break;
case'(':
return8;break;
case'+':
return2;break;
case'-':
return2;break;
case'*':
return4;break;
case'/':
return4;break;
case'^':
return6;break;
case')':
return1;break;
}
}
floatanalyse(floatn,floatm,charch){
switch(ch){
case'+':
return(n+m);break;
case'-':
return(m-n);break;
case'*':
return(n*m);break;
case'^':
return(power(m,n));break;
case'/':
if(n==0){
cout<<"Dividezero!
"<exit(-1);
}
else{
returnm/n;
break;
}
default:
cout<<"Operatorerror!
"<exit(-1);
}
}
floatpower(floatn,floatm){
floatsum=1;
for(inti=0;isum=sum*n;
}
returnsum;
}