资源描述
信息科学与工程学院
综合设计报告书
课程名称: C语言课程设计
班 级:
学 号:
姓 名:
指导教师:
目 录
(一) 需求分析......................................2-3
1. 设计题目;
2. 用户操作流程;
3. 数据处理流程;
(二)概要设计......................................4-5
1. 系统总体设计框架;
2. 系统功能模块图;
(三)详细设计.....................................5-11
1. 主要功能模块的算法设计思路;
2. 工作流程图;
(四)主要源程序代码...............................12-21
1. 完整源程序清单及关键注释;
(五)调试分析过程描述.............................21-24
1. 测试数据、测试输出结果;
2. 对程序调试过程中存在问题的思考;
(六)课程设计小结.................................24-25
1. 包括课程设计过程中的学习体会与收获;
2. 对C语言和本课程设计的认识以及自己的建议等内容。
一、 需求分析
1、 设计题目:
编程实现以下功能:
(1) 分别输入一元多项式pn (x)和Q n (x)。
从键盘输入一元多项式中各项的系数和指数,并用单链表加以表示。
(2) 分别对一元多项式pn (x)和Q n (x)进行升幂排序。
将一元多项式中各子项按照指数从小到大的顺序排序。
(3) 分别输出一元多项式pn (x)和Q n (x)。
将用单链表表示的一元多项式输出,即打印多项式的系数和指数。
(4) 任意输入一个实数x0,分别求出一元多项式pn (x0)和Q n (x0)的值。
(5) 已知有两个一元多项式分别为Pn (x)和Qn (x),求出两个多项式的和
R n (x)和差T n (x),分别用单链表表示R n (x)和T n (x),并将二者输出,
(R n (x)=P n (x)+Q n (x),T n (x)=P n (x)-Q n (x))
2、 用户操作流程:
(1) 进入欢迎及界面。
(2) 根据提示选择需要的功能。
(3) 根据提示输入数据.
(4) 选择函数输出运行结果。
(5) 退出本系统。
3、 数据处理流程
(1) 输入数据,通过链表存储P(x)和Q(x)的指数和系数。
(2) 通过冒泡排序法对P(x)和Q(x)进行升幂排序。
(3) 输入x0,通过指针将其带入P(x)和Q(x)的表达式求出具体的数值。
(4) 通过链表对两个多项式求和求差。
(5) 通过链表输出运行结果。
;
二、 概要设计
1、 系统总体设计框架:
主程序
功能选择函数函数
求差求和函数
输入数据函数
升幂函数
赋值函数
输出结果函数
2、 系统功能模块
(1) 功能选择函数:通过输入对应功能的数字,进行多项式的运算。该函数在主函数中调用。
(2) 输入数据函数:通过建立单链表,输入两个多项式的各项指数和系数。
(3) 升幂函数:通过冒泡排序法对两个多项式进行升幂排序。
(4) 求和求差函数:定义空链用来存储结果,将两个多项式相加减。
(5) 输出函数:输出上一步的运行结果。
三、 详细设计
一元多项式的表示在计算机内可以用链表来表示,为了节省存储空间,只存储多项式中系数非零的项。链表中的每一个结点存放多项式的一个系数非零项,它包含三个域,分别存放该项的系数、指数以及指向下一个多项式项结点的指针。创建一元多项式链表,对一元多项式的运算中会出现的各种可能情况进行分析,实现一元多项式的相加、相减操作。
多项式相加的运算规则是:两个多项式中所有指数相同的项的对应系数相加,若和部位零,则构成“和多项式”中的一项;所有指数不相同的的项均“复抄”到“和多项式”中。以单链表作为存储结构,并且“和多项式”中的节点无需另外生成,则可看做是将多项式Q加到多项式P中,由此得到下列运算规则:
若p->exp<q->exp,则结点p所指的结点应是“和多项式”中的一项,令指针p后移。
若p->exp<q->exp,则结点q所指的结点应是“和多项式”中的一项,将结点q插入在结点p之前,且令指针q在原来的链表上后移。
若p->exp=q->exp,则将两个结点的系数相加,当和不为零是修改结点p的系数,释放q结点;若和为零,则“和多项式”中无 o此项,从P中p结点,同时释放p和q结点。
多项式相减运算规则同加法。
设计思路:
实现的方法是先定义多项式结点的结构,该多项式每个结点由三个元素:输入的系数、输入的指数、以及指向下一个结点的指针构成。该链表采用链式存储结构。然后通过多次的输入,依次得到两个一元多项式的各个项的系数与指数。该输入以零结尾。然后通过对结点的判断是否为零后,进行运算或者终止的操作。再初始化一个链表LC,将LC的各项系数和指数的指针指向LA+LB所得的结果的值,完成了最后的输出。
(1)定义结构体struct
结构体为表示一个对象的不同属性提供了连贯一致的方法,结构体类型的说明从关键词struct开始,成员可以由各种数据类型混合构成,成员甚至还可以是数组或者其他类型的结构,但是,结构体中不能包含自身定义类型的成员。使用typedef和struct定义的新类型名称,其用途与内建类型的名称相同,可以用来:声明和初始化结构体变量;创建并根据自己的意愿初始化结构数组;
(2) 单链表的建立
单链表有两个域,data域和next域,一个是存放数据,一个是存放指针而且指向它的后继。并且还有个head,称表结点,它一般不存放数据,只是做个特殊标记。表的结束是NULL,也就是最后的那个链域next为空单链表的插入运算有两种,一种是头插法,另一种是尾插法,这里运用的是尾插法
(3)一元多项式的建立
输入多项式采用插头的方式,输入多项式中一个项的系数和指数,就产生一个新的节点,建立起它的右指针,并用头节点指向它;为了判断一个多项式是否结束,定义一个结束标志,并输入非0时就继续,当输入0时,就结束一个多项式的输入
(4)显示一元多项式
如果系数是大于0的话就输出+系数x指数形式;如果系数小于0的话输出系数x指数形式;如果指数为0的话,直接输出系数;如果系数是的话就直接输出+x;如果系数是-1的话直接输出-x输出多项式
(5)一元多项式的加法计算
它从两个多项式的头部开始,两个多项式的某一项都不为空时,如果数相等的话,系数就应该相加;相加的和不为0的话,用头插法建立一个新的节点。p的指数小于q的指数的话,就应该复制q节点到多项式中。p的指数大于q的指数的话,就应该复制p节点到多形式中。当第二个多项式为空时,第一个多项式不为空时,将第一个多项式用心节点产生。当第一个多项式为空,第二个多项式不为空时,将第二个多项式用新节点产生
(6)一元多项式的减法计算
它从两个多项式的头部开始,两个多项式的某一项都不为空时,如果数相等的话,系数就应该相减;相加的和不为0的话,用头插法建立一个新的节点。p的指数小于q的指数的话,就应该复制q节点到多项式中。p的指数大于q的指数的话,就应该复制p节点到多形式中。并且建立的节点的系数为原来的相反数;当第二个多项式为空时,第一个多项式不为空时,将第一个多项式用心节点产生。当第一个多项式为空,第二个多项式不为空时,将第二个多项式用新节点产生,并且建立的节点系数为原来的相反数。
数学模型:
在数学上,一个一元多项式Pn(x)可按升幂写成 :
Pn(x)=p0+p1x+p2x2+……+pnxn
它由n+1个系数唯一确定,因此,在计算机中它可用一个线性表P来表示:
P=(p0 ,p1,p2,……,pn)
每一项的指数i隐含在其系数Pi的序号里,每一项的值顺序为各个多项式的系数值。
加法模型:
假设 Qm(X)是一元m次多项式,同样可用线性表Q来表示:
Q=(q0,q1,q2,……qm)
不失一般性,设m<n,则两个多项式相加的结果Rn(x)=P(x)+Q(x)也可用线性表R来表示,为了更具一般性,设n>m ,相加的结果也可以用单链表来表示,规则是相同指数的项的系数相加,所以P(x)+Q(x)=(p0+q0,p1+q1……pm+qm,pm+1……pn),例如:P(x)=2x4+5x2+3x+1,Q(x)=3x2+1,相加后R(x)= 2x4+8x2+3x+2,用一维向量表表示分别为(1,3,5,0,2)+(1,0,3,)=(2,3,8,0,2),写成数学形式即为2x4+8x2+3x+2,结论正确。减法模型同加法模型。
具体函数模块的流程图:
功能选择模块: 输入数据函数:
显示运行结果
调用输出函数
结束
输入各项的指指数系数
开始
开始
判断输入是否合法
通过switch判断返回哪一个功能函数
调用该功能函数
结束
输入功能函数对应的数字
求和函数模块:
开始
定义存储结果的空链 r
是
否
输出存储多项式的和的链r
结束
是
否
同指数项系数相加后存入r中
直接把p中各项存入r中
直接把q中各项存入r
存储多项式2的空链Q是否为空
存储多项式1的空链P是否为空
合并同类项
开始
定义存储结果的空链 r
是
否
输出存储多项式的和的链r
结束
是
否
同指数项系数相加后存入r中
直接把p中各项存入r中
直接把q中各项存入r
存储多项式2的空链Q是否为空
存储多项式1的空链P是否为空
合并同类项
求差函数模块:
开始
定义存储结果的空链 r
是
否
输出存储多项式的和的链r
结束
是
否
同指数项系数相加后存入r中
把p中各项系数改变符号后存入r中
直接把q中各项存入r
存储多项式2的空链Q是否为空
存储多项式1的空链P是否为空
合并同类项
四、 主要源程序代码
#include <stdio.h>
#include <math.h>
#include <algorithm>
typedef struct duoxiangshi
{
int coef;
int exp;
struct duoxiangshi *next;
}DXS;
int getNum()
{
int num;
printf("输入选择功能对应的数字: ");
scanf("%d", &num);
return num;
}
void fun1( DXS *PHEAD, DXS *QHEAD )
{
int zs, xs;//定义指数系数
printf("请输入P(x)中各项的系数和指数\n");
scanf("%d %d", &xs, &zs);
while( zs != 0 || xs != 0 )
{
DXS *p = (DXS*) malloc(sizeof(DXS));
p->coef = xs;
p->exp = zs;
PHEAD->next = p;
p->next = NULL;
PHEAD = PHEAD->next;
scanf("%d %d", &xs, &zs);
}
printf("请输入Q(x)中各项的系数和指数\n");
scanf("%d %d", &xs, &zs);
while( zs != 0 ||xs != 0 )
{
DXS *p = (DXS*) malloc(sizeof(DXS));
p->coef = xs;
p->exp = zs;
QHEAD->next = p;
p->next = NULL;
QHEAD = p;
scanf("%d %d", &xs, &zs);
}
printf("输入5显示结果\n");
}
void fun2( DXS *PHEAD, DXS *QHEAD )//升幂排序
{
DXS *p, *q;//链表的冒泡排序
p = PHEAD->next;
for( p; p != NULL; p = p->next )
{
for( q = p->next; q != NULL; q = q->next )
{
if( p->exp > q->exp )
{
int temp;
temp = p->coef;
p->coef = q->coef;
q->coef = temp;
temp = p->exp;
p->exp = q->exp;
q->exp = temp;
}
}
}
p = QHEAD->next;
for( p; p != NULL; p = p->next )
{
for( q = p->next; q != NULL; q = q->next )
{
if( p->exp > q->exp )
{
int temp;
temp = p->coef;
p->coef = q->coef;
q->coef = temp;
temp = p->exp;
p->exp = q->exp;
q->exp = temp;
}
}
}
printf("输入5显示结果。\n");
}
void fun5( DXS *PHEAD, DXS *QHEAD )
{
printf("当前保存的P(x),Q(x)序列如下:\n");
printf("P(x)=");
while( PHEAD->next != NULL )
{
PHEAD = PHEAD->next;
printf("%d*x^%d", PHEAD->coef, PHEAD->exp);
if( PHEAD->next != NULL )
{
printf(" + ");
}
}
printf("\n");
printf("Q(x)=");
while( QHEAD->next != NULL )
{
QHEAD = QHEAD->next;
printf("%d*x^%d", QHEAD->coef, QHEAD->exp);
if( QHEAD->next != NULL )
{
printf(" + ");
}
}
printf("\n\n");
}
void fun4( DXS *PHEAD, DXS *QHEAD )
{
int x0;
double sum;
printf("输入x的值: ");
scanf("%d", &x0);
sum = 0;
while( PHEAD->next != NULL )
{
PHEAD = PHEAD->next;
sum += PHEAD->coef * pow( x0, PHEAD->exp );
}
printf("P(x) = %.0lf\n", sum);
sum = 0;
while( QHEAD->next != NULL )
{
QHEAD = QHEAD->next;
sum += QHEAD->coef * pow( x0, QHEAD->exp );
}
printf("Q(x0) = %.0lf\n\n", sum);
}
void fun3( DXS *PHEAD, DXS *QHEAD )//求两个多项式的和差
{
fun2( PHEAD, QHEAD );//先进行升幂排序
DXS *RHEAD, *THEAD;
RHEAD = (DXS*) malloc(sizeof(DXS));
THEAD = (DXS*) malloc(sizeof(DXS));
RHEAD->next = NULL;
THEAD->next = NULL;
DXS *p = PHEAD, *q = QHEAD;
//多项式相加
DXS *r = RHEAD;
p = p->next;
q = q->next;
while( p != NULL && q != NULL )//当两个序列都有数值时
{
DXS *t = (DXS*) malloc(sizeof(DXS));
if ( p->exp == q->exp )//指数相同的情况
{
t->coef = p->coef + q->coef;
t->exp = p->exp;
p = p->next;
q = q->next;
}
else if( p->exp < q->exp )//P的指数小于Q的指数
{
t->coef = p->coef;
t->exp = p->exp;
p = p->next;
}
else if( p->exp > q->exp )//P的指数大于Q的指数
{
t->coef = q->coef;
t->exp = q->exp;
q = q->next;
}
r->next = t;
r = r->next;
r->next = NULL;
}
while ( p != NULL )//当只有一个序列有数值时
{
DXS *t = (DXS*) malloc(sizeof(DXS));
t->coef = p->coef;
t->exp = p->exp;
r->next = t;
r = r->next;
r->next = NULL;
p = p->next;
}
while ( q != NULL )
{
DXS *t = (DXS*) malloc(sizeof(DXS));
t->coef = q->coef;
t->exp = q->exp;
r->next = t;
r = r->next;
r->next = NULL;
q = q->next;
}
r = RHEAD;
printf("R(x) = ");
while( r->next != NULL )
{
r = r->next;
if (r->coef>=0)
{
if(r!=RHEAD->next)
printf(" + ");
printf("%d*x^%d",r->coef,r->exp);
}
else
printf(" - %d*x^%d",-1*r->coef,r->exp);
}
printf("\n\n");
//多项式相减
p = PHEAD;
q = QHEAD;
DXS *T = THEAD;
p = p->next;
q = q->next;
while( p != NULL && q != NULL )
{
DXS *t = (DXS*) malloc(sizeof(DXS));
if ( p->exp == q->exp )
{
t->coef = p->coef - q->coef;
t->exp = p->exp;
p = p->next;
q = q->next;
}
else if( p->exp < q->exp )
{
t->coef = p->coef;
t->exp = p->exp;
p = p->next;
}
else if( p->exp > q->exp )
{
t->coef = -1 * q->coef;
t->exp = q->exp;
q = q->next;
}
T->next = t;
T = T->next;
T->next = NULL;
}
while ( p != NULL )
{
DXS *t = (DXS*) malloc(sizeof(DXS));
t->coef = p->coef;
t->exp = p->exp;
T->next = t;
T = T->next;
T->next = NULL;
p = p->next;
}
while ( q != NULL )
{
DXS *t = (DXS*) malloc(sizeof(DXS));
t->coef = -1 * q->coef;
t->exp = q->exp;
T->next = t;
T = T->next;
T->next = NULL;
q = q->next;
}
T = THEAD;//消除系数为0项
while ( T->next != NULL )
{
if( T->next->coef == 0 )
{
T->next = T->next->next;
}
T = T->next;
if( T == NULL )
break;
}
T = THEAD;
printf("T(x) = ");
while( T->next != NULL )
{
T = T->next;
if( T->coef >=0 )
{
if(T!=THEAD->next)
printf(" + ");
printf("%d*x^%d",T->coef,T->exp);
}
else
printf(" - %d*x^%d", -1 * T->coef, T->exp);
}
if (THEAD->next==NULL)
printf("0\n");
printf("\n");
}
void menu()
{
printf("-----------------------------------------------\n");
printf("1.分别输入Pn(x)和Qn(x)。\n");
printf("2.分别对Pn(x)和Qn(x)进行升幂排序。\n");
printf("3.分别求出Pn(x)和Qn(x)的和差。\n");
printf("4.任意输入一个实数x,分别求出一元多项式Pn(x)和Qn(x)的值。\n");
printf("5.分别输出上一步运行结果的Pn(x)和Qn(x)。\n");
printf("-----------------------------------------------\n");
printf("If you want to exit the system,please input 0.\n");
}
int main()
{
printf("Welcome to the menu~~\n");
menu();
int num;
num = getNum();
if ( num == 0 )
printf("\nExit the system,goodbye~~\n");
DXS *PHEAD, *QHEAD;
PHEAD = (DXS *)malloc(sizeof(DXS));
QHEAD = (DXS *)malloc(sizeof(DXS));
PHEAD->next = NULL;
QHEAD->next = NULL;
while ( num )
{
switch ( num )
{
case 1:
fun1( PHEAD, QHEAD ); break;
case 2:
fun2( PHEAD, QHEAD ); break;
case 3:
fun3( PHEAD, QHEAD ); break;
case 4:
fun4( PHEAD, QHEAD ); break;
case 5:
fun5( PHEAD, QHEAD ); break;
default:
printf("输入错误,请重新输入\n\n");
}
num = getNum();
if ( num == 0 )
printf("\nExit the system,goodbye!\n");
}
return 0;
}
五、 调试分析过程描述
测试数据及实验过程:
1、欢迎界面以及选择功能1和功能5得到的结果:
2、调用功能2对应的函数并输出结果
2、调用功能2对应的函数:
3、 调用功能3对应的函数:
4、 调用功能4对应的函数:
5、退出本系统:
调试:
当输入的两个多项式相同时,相减结果应为0,但T(X)显示的是0*x^4。此时应当修改功能函数,当指数相同系数也相同的项相减时,释放p,q指针所指向的结点,输出0。修正常改程序后,正常输出。
在此之前也遇到了一些问题,同样是减法函数,如果P,Q中相同指数对应的项相减时负数,刚开始输出的是“+ -x”,即加上负的差值,通过修改代码,在原先函数功能的基础上增加判断条件:
If(T->coef>=o)
{
if(T!=THEAD->next)
printf(“ + ”);
printf(“%d*x^%d,T->coef,T->exp);
}
else
printf(“ - %d*x^%d”,-1*T->coef,T->exp);
六、 设计小结
学习体会与心得:
通过对一元多项式的研究我们看到一元n次多项式与n维线性空间同构,这极大的扩展了其在工程领域的计算问题,在计算机中能够实现n维空间的四则运算,这实际上是用计算机来解决数学问题,研究最基本的运算规律,为数学研究提供了很大的帮助。
实现的方法是先定义多项式结点的结构,该多项式每个结点由三个元素:输入的系数、输入的指数、以及指向下一个结点的指针构成。该链表采用链式存储结构。然后通过多次的输入,依次得到两个一元多项式的各个项的系数与指数。该输入以零结尾。然后通过对结点的判断是否为零后,进行运算或者终止的操作。再初始化一个链表LC,将LC的各项系数和指数的指针指向LP+LQ所得的结果的值,完成了最后的输出。
根据上述的源程序,可以得到一元多项式计算的运行结果,采用单链表形式按照指数降序排列建立并输出多项式,实现两个多项式相加,相减。输入一元多项式的项数,根据提示输入3个非零项,这是界面出现了几个选项,我们可以在这里实现一元多项式的加法,减法,升幂排序,赋值等功能的实现。
课程设计是培养学生综合运用所学知识,发现,提出,分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际工作能力的具体训练和考察过程.随着科学技术发展的日新日异,当今计算机应用在生活中可以说得是无处不在。因此作为二十一世纪的大学来说掌握计算机开发技术是十分重要的。
回顾起此次课程设计,至今我仍感慨颇多,的确,从从拿到题目到完成整个编程,从理论到实践,在短短的半个多月里,可以学到很多很多的的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。在设计的过程中遇到问题,可以说得是困难重重,难免会遇到过各种各样的问题,同时在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固,比如说结构体……通过这次课程设计之后,一定把以前所学过的知识重新温故。
展开阅读全文