数据结构课程设计用两种方式实现表达式自动计算Word下载.docx
《数据结构课程设计用两种方式实现表达式自动计算Word下载.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计用两种方式实现表达式自动计算Word下载.docx(20页珍藏版)》请在冰豆网上搜索。
流程图说明:
该流程图分两部分成,第一部分是中缀转后缀部分,第二部分是用于后缀表达式求值的。
(二)直接计算算法的流程图
图2接计算算法的流程图
该流程图进过图1改进得到,只是缺少中缀转后缀的部分。
三、源代码
下面给出的是用中缀转后缀算法实现的程序的源代码:
#include<
stdio.h>
#defineN50
typedefstructStackArray{
floatdata[N];
inttop;
}StackArray;
/*定义操作数栈*/
typedefstructStackChar{
chardata[N];
}StackChar;
/*定义操作符栈*/
StackArray*InitNum()/*初始化数值栈*/
{
StackArray*p=(StackArray*)malloc(sizeof(StackArray));
/*取一段内存赋予数值栈*/
p->
top=-1;
returnp;
/*返回*/
}
StackChar*InitChar()/*初始化操作符栈*/
StackChar*p=(StackChar*)malloc(sizeof(StackChar));
intPushNum(StackArray*p,floatvalue)/*定义入栈函数*/
if(p->
top<
50-1)
{
top+=1;
data[p->
top]=value;
/*栈顶*/
return1;
}
else
return0;
intPushChar(StackChar*p,charvalue)/*操作符入栈*/
/*入栈为栈顶*/
/*返回值*/
intPopNum(StackArray*p,float*value)/*操作数出栈*/
top>
=0)/*判断栈是否为空*/
*value=p->
top];
top-=1;
intPopChar(StackChar*p,char*q)/*操作符出栈函数*/
if(p->
=0)/*定义操作符栈*/
*q=p->
floatVisitNum(StackArray*p)/*定义数值栈遍历函数*/
top!
=-1)
returnp->
elsereturn0;
charvisitChar(StackChar*p)/*定义操作符栈遍历函数*/
intlevel(charc)/*优先级*/
switch(c)
case'
#'
:
/*#的优先级*/
+'
return1;
-'
/*‘-‘的优先级*/
*'
return2;
/'
('
return3;
/*(优先级*/
default:
return-1;
intstrLen(char*L)/*字符串长度函数*/
inti;
for(i=0;
L[i]!
='
\0'
;
i++);
/*循环条件*/
if(L[0]=='
||L[0]=='
)
{
i=i-1;
returni;
floatCompute(floata,charc,floatb)/*计算*/
returna+b;
/*加号的运算*/
returna-b;
returna*b;
/*乘号的运算*/
returna/b;
/*除号的运算*/
voidmain()
StackArray*data;
StackChar*op;
inti,j=0;
floatn;
floatresult,opA,opB;
charopChar;
chararray[N];
char*ptarray=NULL;
/*定义指针*/
floathouzhui[N];
printf("
Pleaseenteradata:
\t"
);
while((scanf("
%s"
array))!
=EOF)/*循环条件*/
op=InitChar();
data=InitNum();
PushChar(op,'
array[strLen(array)]='
/*结束标志*/
ptarray=array;
i<
strLen(ptarray);
i++)/*循环条件*/
if(array[i]>
=48&
&
array[i]<
=57||array[i]=='
.'
)/*判断数值
doubleweight=0.1;
intflag=0;
/*定义变量*/
floatn=0;
n=array[i]-48;
while(array[i+1]>
array[i+1]<
=57||array[i+1]=='
)/*判定数值*/
if(array[i+1]=='
)/*小数*/
flag=1;
if(flag==0)n=n*10+array[i+1]-48;
/*整数化浮点数*/
n=n+(array[i+1]-48)*weight;
/*小数化浮点数*/
weight*=0.1;
/*小数位权*/
i++;
houzhui[j]=n;
j++;
if(array[i]=='
)/*结束标志*/
while(visitChar(op)!
)/*对操作符栈遍历*/
PopChar(op,&
opChar);
houzhui[j]=opChar;
/*出栈入数组*/
if(level(array[i])>
level(visitChar(op))||
visitChar(op)=='
)/*判断优先级*/
PushChar(op,array[i]);
/*入栈*/
)'
)/*遇见字符‘)’*/
)/*出战到‘(’*/
j++;
/*操作符入数组*/
}
}else
while(level(array[i])<
=
level(visitChar(op)))/*优先级*/
/*出栈*/
/*运算符进栈*/
for(j=0;
houzhui[j]!
j++)
if((char)houzhui[j]=='
||(char)houzhui[j]=='
||
(char)houzhui[j]=='
)/*类型转换*/
%2c"
(char)houzhui[j]);
/*输出一个运算符*/
PopNum(data,&
opA);
opB);
result=Compute(opB,(char)houzhui[j],opA);
/*调用函数*/
PushNum(data,result);
/*结果入栈*/
PushNum(data,houzhui[j]);
%8f"
houzhui[j])/*输出后缀表达式*/;
\ntheResultis:
%.2f\n\n"
result);
/*输出结果*/
下面给出的是用直接计算算法实现的程序的源代码:
typedefstructlistStack
floatdata[N];
inttop;
}listStack;
/*定义存储操作数的栈*/
typedefstructopStack
chardata[N];
}opStack;
/*用于定义存储操作符号的栈*/
listStack*InitNum()/*初始化数值栈*/
listStack*p=(listStack*)malloc(sizeof(listStack));
top=-1;
/*定义栈底*/
returnp;
opStack*InitChar()/*初始化操作符栈*/
opStack*p=(opStack*)malloc(sizeof(opStack));
/*取一段内存赋予操作符栈*/
p->
top=-1;
intPushNum(listStack*p,floatvalue)/*定义入栈函数*/
N-1)
/*入栈的数值为栈顶元素*/
else
return0;
intPopNum(listStack*p,float*a)/*定义数值出栈函数*/
=0)/*判定栈不为空*/
*a=p->
floatVisitNum(listStack*p)/*定义数值栈遍历函数*/
=-1)/*判定栈是否为空*/
returnp->
elsereturn0;
voidPushChar(opStack*p,chara)/*定义操作符入栈函数*/
top]=a;
/*入栈字符为栈顶元素*/
else;
intPopChar(opStack*p,char*a)/*定义操作符出栈函数*/
charvisitChar(opStack*p)/*定义操作符栈遍历函数*/
/*返回栈顶的值*/
intstrLen(char*L)/*计算字符串长度*/
inti;
for(i=0;
/*循环条件的判定*/
if(L[0]=='
i=i-1;
returni;
intlevel(charc)/*符号的优先级*/
switch(c)
case'
default:
floatCompute(floata,charch,floatb)/*数据运算*/
switch(ch)
/*返回加号数值运算*/
/*返回减号数值运算*/
/*返回除号数值运算*/
return-1;
listStack*data;
/*定义操作数栈,由指针data指出*/
opStack*op;
/*对变量进行声明*/
floatn;
floatresult,opA,opB;
charoperand[2],opChar;
/*定义字符型数组和字符变量*/
chararray[N];
char*ptarray=NULL;
/*定义字符型指针*/
printf("
while((scanf("
=EOF)/*判断循环的条件*/
op=InitChar();
data=InitNum();
PushChar(op,'
/*将字符#赋予数组最后*/
ptarray=array;
i++)/*判定循环的条件*/
if(array[i]>
=57||
array[i]=='
)/*判断值*/
doubleweight=0.1;
intflag=0;
/*定义整形变量flag*/
/*定义浮点型变量*/
while(array[i+1]>
array[i+1]=='
)
flag=1;
/*读到小数点*/
/*将整数部分字符串转化为实数*/
/*将表示小数部分的字符也转化过来*/
weight*=0.1;
/*weight为小数位权*/
i++;
PushNum(data,n);
/*将数值进栈*/
)/*遇见字符#*/
while(visitChar(op)!
)/*对操作符栈进行遍历*/
PopChar(op,&
/*字符出栈*/
PopNum(data,&
/*数出栈*/
result=Compute(opB,opChar,opA);
/*调用运算函数*/
PushNum(data,result);
if(level(array[i])>
visitChar(op)=='
)/*判断操作符的优先级高低*/
PushChar(op,array[i]);
/*操作符进栈*/
)/*当操作符为)时*/
)/*遍历操作符栈*/
/*从数值栈输出一个值*/
result=Compute(opB,opChar,opA);
/*结果放回栈里*/
/*输出操作符*/
while(level(array[i])<
=level(visitChar(op)))/*判断操作符的优先级高低*/
/*从数值栈输出数值*/
esult=Compute(opB,opChar,opA);
/*将运算结果入栈*/
/*将操作符入栈*/
theResultis:
%.6f\n\n"
/*输出扫描一遍的运算结果*/
四、运行结果
(一)中缀转后缀算法的运行结果:
图3中缀转后缀算法的运行结果
(二)直接计算算法的运行结果:
图4直接计算算法的运行结果
五、遇到的问题及解决
这部分我主要遇到了如下两个问题,其内容与解决方法如下所列:
●问题1:
在遇到小数点处理的问题上,虽然说处理小数点的方法不是唯一的,但我在处理的时候只能计算一位小数,如果输入的是两位的话,计算结果的时候它就把一位小数后面的数据全丢了。
解决方法:
在输出后缀表达式的时候可以看到栈里存的数据最多只带一位小数,所以结果也只能出现一位小数。
因为在处理小数的时候我是让小数点后面的数乘以0.1,再加上前面的。
但如果是两位的话,那么最后的那一个是要乘以0.01的,也就是乘以0.1的自乘,所以在处理小数时我加了自乘的这行代码,运行的结果才真确的出来了。
●问题2:
无论输入什么表达式,不知道结果为什么始终是‘0.00‘,运行还是行的,有的时候程序只是按照扫到最后的一个运算符来执行。
图5运行出错
刚开始不知道哪儿出错了,就瞎找那些有可能会出现错的地方,比如:
能从图中直接看出来,没有后缀表达式;
计算结果也是错误的;
还有可能是哪个函数调用时出了错。
随后就从最简单的函数调用出错的问题开始检查,没有发现什么明显的错误,就放弃了这个问题,接着就是计算有没有出现简单的错误,因为它比较于中缀转后缀要简单一些,就开始试,单独的对这一段代码试,结果还是没发现什么错误,最后就剩下最难的中缀转后缀的问题了,如果这个也没有错,那就不知道哪儿出错了,就开始对它调试,看了两个小时也没找出来什么错误。
以后才找到那儿出了漏洞,原来缺少一句赋值语句“houzhui[j]=n;
”就成这样了,这个错误告诉我一点点的小错误也能导致整个程序的错误。
六、心得体会
通过这次的作业我充分的认识到了自己的不足,特别是对写程序代码这方面,一个程序从算法到用程序把它实现出来,这一整个过程是很不容易的,你懂得它的算法,不一定就能写的出来,通过这次我也深深的了这一点。
对于一个新手来说,小的错误出现的太多,而且一个小的错误就能让我束手无策,因为想不通错在哪,所以就一直在乱改,逻辑错误就更难了,有时候程序运行语法没有错误,但只要输入表达