003课程设计报告10065012舒焕.docx
《003课程设计报告10065012舒焕.docx》由会员分享,可在线阅读,更多相关《003课程设计报告10065012舒焕.docx(18页珍藏版)》请在冰豆网上搜索。
![003课程设计报告10065012舒焕.docx](https://file1.bdocx.com/fileroot1/2023-2/6/bddd0821-e9f8-4ff5-a96c-b45c542f6f69/bddd0821-e9f8-4ff5-a96c-b45c542f6f691.gif)
003课程设计报告10065012舒焕
表达式类型的实现
一目的
熟练掌握《数据结构》课程的相关知识,完成一个具有一定难度的综合设计题目,熟练使用c/c++语言进行程序设计,并且规范完成课程设计报告。
巩固《数据结构》里的字符串,树等理论知识的理解,掌握现实复杂问题的分析建模和解决方法,提高利用计算机分析解决综合性实际问题的基本能力。
二需求分析
1、功能
1、将前缀表达式输入到字符串数组中,并且存储到二叉树中。
2、将二叉树中的表达式以中缀的表达式形式输出,有必要的地方加()。
3、对存储前缀表达式的字符串数组进行查询,有未知变量的进行赋值,并且赋值完后存储到该字符串数组中。
并且更新二叉树里的数据。
4、对已经赋值完了的二叉树进行求值。
2、输入
输入的形式以字符串的形式输入到字符串数组中,并且输入的数字字符都是个位数的运算,不能执行十位以上的运算。
可以输入未知变量,如a,b,c,当对未知变量赋值时,未知变量可以是十位以上的数字,但在运算过程中,结果不得超过256,也就是asc码的范围。
例如输入0;a;-91;+a*b5;+-9/62-ab4。
3、输出
该程序的输出分为两步,第一步:
将前缀表达式转化为中缀表达式,存储到字符串数组中,并输出;第二步:
输出表达式测试的结果,并判断是否正确。
对上面的输入,正确的输出应该为0;a;9-1;a+b*5;9-6/2*(a-b)+4;
三概要设计
1、变量定义
宏定义的有,MAXSTR,表示表达式的长度最大限度。
全局变量定义,char类型的str[MAXSTR],用来存储前缀表达式;char类型的str1[MAXSTR],用来存储中缀表达式,并且有必要加括号的时候也包含括号;结构体类型的树和全局变量树指针T,具体定义如下:
typedefstructBitNode{
unsignedchardata;
intstatus;
structBitNode*lchild,*rchild;
}BitNode,*BitTree;
Int类型的overflow,表示当数据大于256时,溢出,不能用符号的asc码表示,需要做一定的处理,int类型的m,用来存储溢出时是256的多少倍。
2、模块设计
模块分为四个模块,前缀表达式的输入模块,中缀表达式输出模块(必要时带号),给未知变量赋值模块,求值模块。
1、前缀表达式输入模块分为两个函数
voidinput()输入前缀表达式函数,判断前缀表达式的正确性,正确之后存储到全局变量str中,
voidcreatBT(BitTree&T1,int&i),将前缀表达式存储到二叉树中。
2、中缀表达式输出模块的函数为
voidout_express(BitTreeT,int&len)
以中缀的形式读取二叉树中的数据,并判断运算符的优先级,在必要的地方加入括号,存储到str1数组中,
voidout_express(BitTreeT,int&len)函数中嵌套有
charprecedence(charzifu_child,charzifu_parents)函数,
判断运算符的优先级,其中
charprecedence(charzifu_child,charzifu_parents)又嵌套
intcharToint(charzifu)函数
intcharToint(charzifu)将运算符的优先级用数字来表示,并且比较大小。
3、未知变量赋值模块包含两个函数
voidassignment()
函数将str[]数组中的未知变量赋值并且将赋值以后的数据存储到str[]数组中
voidcreatBT(BitTree&T1,int&i)
以中缀的形式存储到二叉树中。
4、求值模块函数为
voidcout(BitTree&T1)
该函数将结果转化为字符并且存储在二叉树的头结点中。
四详细设计
1、变量定义
#defineMAXSTR50表示表达式的长度最大限度
typedefstructBitNode{
unsignedchardata;
intstatus;//用来表示表达式的变量1,常量2,运算符3,
structBitNode*lchild,*rchild;
}BitNode,*BitTree;
charstr[MAXSTR];//全局变量,用来存储前缀表达式,用来输入
charstr1[MAXSTR];//全局变量,用来存储中缀表达式,并且输出
intoverflow=0;//判断结果是否超出字符最大的ASCII码数字255;
intm;//用来存储溢出时是256的多少倍。
BitTreeT;//用来存储数据的二叉树指针
2、模块设计
1、前缀表达式输入函数
voidinput(){该函数用存储前缀表达式
inti;
intlength;
intchar_num,int_num;
char_num=0;int_num=0;
printf("请输入正确的前缀表达式");
scanf("%s",str);
if(str[0]!
='+'&&str[0]!
='-'&&str[0]!
='*'&&str[0]!
='/')//第一个不是运算符,则前缀表达式输入错误
printf("表达式输入错误,请从新输入一遍\n");
length=strlen(str);
for(i=0;i{
if(str[i]=='+'||str[i]=='-'||str[i]=='*'||str[i]=='/')
char_num++;
else
int_num++;
}
if(int_num!
=char_num+1)//如果变量的个数不是等于运算符的个数,则前缀表达式输入错误
printf("表达式输入错误,请从新输入一遍\n");
}并且存储到二叉树中用到函数voidcreatBT(BitTree&T1,int&i){
T1=(BitTree)malloc(sizeof(BitTree));
if(str[i]=='\0')
return;
if(str[i]<='9'&&str[i]>='0')
{
T1->data=str[i];
T1->status=2;
T1->lchild=T1->rchild=NULL;
}
elseif(str[i]=='+'||str[i]=='-'||str[i]=='*'||str[i]=='/')//将运算符存储在根节点
{
T1->data=str[i];
T1->status=3;
i++;
creatBT(T1->lchild,i);
i++;
creatBT(T1->rchild,i);
}
elseif(str[i]<='z'&&str[i]>='a')
{
T1->data=str[i];
T1->status=1;
T1->lchild=T1->rchild=NULL;
}
}该函数将数组str中的表达式存储到二叉树中
2、中缀表达式输出函数
voidout_express(BitTreeT,int&len){
chartemp;
if(!
T)return;
if(T->lchild){
if(T->lchild->status!
=3)str1[len++]=T->lchild->data;
else{
temp=precedence(T->lchild->data,T->data);判断做孩子与根节点运算符的优先级,必要时加上括号。
并且存储到str1[]数组中
switch(temp){
case'<':
str1[len++]='(';
out_express(T->lchild,len);
str1[len++]=')';
break;
case'=':
case'>':
out_express(T->lchild,len);
break;
}
}
}
str1[len++]=T->data;
if(T->rchild){
if(T->rchild->status!
=3)str1[len++]=T->rchild->data;
else{
temp=precedence(T->rchild->data,T->data);
switch(temp){
case'<':
str1[len++]='(';
out_express(T->rchild,len);
str1[len++]=')';
break;
case'=':
case'>':
out_express(T->rchild,len);
break;
}
}
}
}其中嵌套函数charprecedence(charzifu_child,charzifu_parents){
chartemp;
intm,n;
m=charToint(zifu_child);
n=charToint(zifu_parents);
if(m-n>0)
{
temp='>';
returntemp;
}
elseif(m-n==0)
{
temp='=';
returntemp;
}
else{
temp='<';
returntemp;
}
}再嵌套函数intcharToint(charzifu){
if(zifu=='+'||zifu=='-')
return1;
if(zifu=='*'||zifu=='/')
return2;
return0;
}
3、赋值函数
voidassignment(){
charbianliang[MAXSTR];
intk=1,j,str_length;
intc;
str_length=strlen(str);
for(inti=0;iif(str[i]<='z'&&str[i]>='a')搜索变量并且存储到bianliang【】数组中
{
bianliang[k]=str[i];
for(j=1;jif(bianliang[j]==bianliang[k])变量有重复就舍去,
{
bianliang[k]='\0';
k--;
}
k++;
}
for(j=1;j{
printf("第%d个变量%c赋值为:
\n",j,bianliang[j]);
scanf("%d",&c);给变量赋值
for(i=0;iif(str[i]==bianliang[j])赋值以后存储到str【】数组中
str[i]=c+'0';
}
printf("用来测试赋值是否成功%s\n",str);
}
4、求值函数
voidcout(BitTree&T1){用后跟遍历的方法求二叉树中的值,并且用递归的方法
inta,b,result;
if(!
T1->lchild&&!
T1->rchild)
return;
if(T1->lchild->status==3)
cout(T1->lchild);
if(T1->rchild->status==3)
cout(T1->rchild);
if(T1->lchild->status==2&&T1->rchild->status==2)
{
a=T1->lchild->data-48;
b=T1->rchild->data-48;
switch(T1->data)
{
case'+':
result=a+b;break;
case'-':
result=a-b;break;
case'*':
result=a*b;break;
case'/':
result=a/b;break;
}
if(result+48>255)//溢出,超出asc码的范围,特殊处理
{
m=(result+48)/256;
overflow=1;
result=result+48-256*m;
}
T1->data=result+48;
T1->status=2;
}
}
五调试分析
1、输入模块
输入前缀表达式时,基本的判断了前缀表达式是否正确,但更深层次的判断还没有实现。
比如首字符必须为运算符,运算符比变量少一个。
这种判断能实现,但如果像*222*这种前缀表达式就不能判断,会使程序出问题。
现在还没得到解决。
2、中缀表达式输出
通过中根遍历的方法,比较运算符的优先级,在需要时加上括号,并且都存储到数组str1[]主要还是递归的方法,这个函数没出什么问题。
3、赋值函数
首先在数组str中找出未知变量,存储到bianliang数组中,重复的未知变量记录一次,利用循环在str数组中找到与bianliang数组中对应的字符并赋值。
这时,出现了一个问题,就是当赋值时,用到scanf("%c",&c),str[i]=c出错,然后更改c为int型的数据,并且用scanf("%d",&c);赋值str[i]=c+'0',这时才正确,虽然改对了,但还是不懂为什么。
4、求值函数
只有一个问题,就是当数据结果大于256时,超出了asc码的范围,就需要用到溢出overflow变量来处理,将结果减去溢出256的多少倍,就能用符号存储了,在输出结果时再加上减去的数据就可以了。
六测试结果
开始运行程序,显示菜单,选择1,输入表达式,
表达式输入错误后,又回到菜单,选择1,重新输入表达式0,并且选择2,查看表达式
又重新输入1,测试任务书里给的数据,查看程序结果是否正确。
继续测试表达式数据-91.
测试有未知变量的表达式数据+a*b5。
测试有未知数据并且转换成中缀表达式有括号的表达式数据+-9*/62-ab4。
选择3,给表达式赋值,然后选择4,给表达式求值。
测试若果结果超出asc码的范围,计算结果是否正确。
选择菜单之外的选择时,提示输入错误。
选择0,结束程序运行。
七用户使用说明
1、本程序的运行环境为vc6.0执行文件为expressText.cpp
2、用户界面为
3、用户只需要根据提示来输入。
4、若要退出只需输入0。
八课程设计总结
在这次课程设计中,我学会了很多东西,并且也温习了之前所学的一些知识。
对二叉树的运用,以及在遍历二叉树时所用到的递归算法。
尤其在前缀表达式转化为中缀表达式和二叉树求值的时候,递归用得特是时候,非常的好。
其次在赋值模块里,也通过全局变量数组来存储变量,并且在for循环的作用下,给每一个变量赋值,然后存储到二叉树中,最后求值。
不过,在这次程序设计中,也遇到了跟多困难,主要是在求值模块里,当数据超出范围,也就是asc码的范围256,就要通过减去256的多少倍来实现运算。
但还不是很完美,在运算当中如果出现溢出,就会出错,但我现在还不知道怎么处理,只有最后结果溢出,才能处理。
不过在以后的学习中,我还会跟加努力的学习。