C程序设计基础课程设计设计报告链表建立学生成绩管理系统Word下载.docx
《C程序设计基础课程设计设计报告链表建立学生成绩管理系统Word下载.docx》由会员分享,可在线阅读,更多相关《C程序设计基础课程设计设计报告链表建立学生成绩管理系统Word下载.docx(36页珍藏版)》请在冰点文库上搜索。
![C程序设计基础课程设计设计报告链表建立学生成绩管理系统Word下载.docx](https://file1.bingdoc.com/fileroot1/2023-5/7/4ecc4910-c046-4fef-8547-08f403c7fee7/4ecc4910-c046-4fef-8547-08f403c7fee71.gif)
利用关系模型和关系数据库系统,使数据以二维表的形式表示,数据结构简单清晰,易学易用。
3.详细设计说明
3.1题目设计分析
3.1.1需求分析
《学生成绩管理系统》是应用于学生考试成绩存储的简易系统。
通过该系统可以创建、增加、删除、查询学生的个人信息,统计学生考试情况,并可以存储到指定目录的文件中,以达到创建数据库管理系统的目的。
3.1.2解题思路分析
首先,分析《学生成绩管理系统》的主要功能模块。
该系统组要分为两大模块:
一是,对数据信息的增删改查;
二是,对已有信息的统计。
其次,分析该系统的实现方式。
该系统为链表的具体应用,需要熟练掌握链表及文件读写的相关知识。
另外,需要将每个具体功能编写为单一的被调函数,主函数实现输入输出功能,以达到优化程序的目的。
最后,运行并调试程序,更改程序错误,优化程序功能。
3.2设计过程
3.2.1链表(结构体)定义
structnode
{intnum;
charnam[N];
charcol[N];
charcla[N];
floatmath;
floateng;
floatclan;
floatsum;
floatave;
structnode*next;
};
3.2.2函数编写
●主函数voidmain()
主函数voidmain()实现各功能的选择,分为创建、增加、删除、修改、查询,以及统计等功能,而各功能分别编写为被调函数。
利用while循环实现用户的人性化操作,以达到结束程序或继续运行程序的目的。
创建、增加、删除、修改、查询、统计等被调函数,都须写于主函数之上;
利用switch()函数实现各功能的选择。
对数据的增、删、改操作,必须返回结构退指针,而查找功能只需要输出即可。
●创建链表structnode*creat(void)
创建新链表函数,返回链表头指针。
定义结构体指针变量“structnode*h=NULL,*p,*q,*r;
”。
h为头指针,及数据表的表头;
动态分配内存给p,令其始终指向新节点;
而q,r而中间辅助指针,是链表按要求链接。
在创建链表的过程中,动态分配内存给指针p,分别输入学生信息,并进行数据计算与赋值。
在节点连接的过程中,通过对输入学号大小的比较while((p->
num>
q->
num)&
&
(q->
next!
=NULL)),按学号排序连接节点,使学号以升序排列。
在输入玩一个信息之后,会有提示信息询问是否继续。
●增加新节点structnode*insert(structnode*h)
增加过程与创建过程大致相同,唯一不同的是,增加过程需要得到形参继续增加学生信息。
●删除节点structnode*del(structnode*h,intn)
删除节点实质就是,将链表指针所指向的地址在内存中擦除。
主要分为两种情况:
删除头指针所指向的节点地址和删除中间或结尾的节点地址。
首先,需要判断所删除节点的地址“while((p->
num!
=n)&
(p!
=NULL))”,然后,进行逻辑判断,是否存在该学号的节点,以及判断是否为头指针,并将p的内存空间释放掉:
“if(p==h)h=p->
next;
elseq->
next=p->
free(p);
M--;
printf("
M:
%d\n"
M);
puts("
Delete!
"
);
”。
●修改节点structnode*modify(structnode*h)
即删除和增加过成功地结合。
进行
●查找节点
查找节点,即根据所查询的信息查找记录,需要定义结构体指针变量p,进行逻辑判断即可。
while((strcmp(p->
nam,nam)!
=0)&
(p->
=NULL))p=p->
if(strcmp(p->
nam,nam)==0)
●统计平均分分数段
需要根据创建(或增加)时计算出的平均分各分数段的个数,来统计。
分为A,B,C,D,E五个分数段,若链表中的平均分满足判断条件,如if((p->
ave>
=90)&
ave<
=100)),则该分数段统计个数加一a[0]++;
。
●查找最高成绩的学生
与查找节点的算法相似,但是逻辑判断必须满足while(p!
=NULL),if(p->
sum==max),这样即使是相同分数的学生也可以同时输出到屏幕上。
●统计不及格率
需要定义全局变量M,然后根据各科不及格的人数n计算出不及格率:
“printf("
TheRATEof%c-Failer:
%.2f%c\n"
c,(a[2]/(float)M)*100,37);
”
●按最高分排序
按最高分排序需要建立新的链表。
然后根据总分成绩进行排序。
structnode*h1=NULL,*p,*a=NULL,*b,*c=NULL;
structnode*sta_sor(structnode*h){structnode*h1=NULL,*p,*a=NULL,*b,*c=NULL;
if(h==NULL){returnNULL;
}//creatnewlinkpoint//h1:
a,b,c;
//bisthelatestcopiedinformationp=h;
//starttocopy&
comparetheinformationconstantlywhile(p!
=NULL){b=copyasta(p);
if(c==NULL){h1=b;
//ifh1isnull,insertb//printf("
insert%dbeforeh1\n"
b->
num);
}else{if(a==NULL&
b->
sum>
=c->
sum){b->
next=c;
h1=b;
//printf("
2在最前面插入%d\n"
c=h1;
a=NULL;
p=p->
continue;
}a=h1;
c=a->
do{if(c==NULL){a->
next=b;
break;
}//compareif(b->
sum){b->
a->
next=b;
break;
}a=c;
c=c->
}while(c!
=NULL);
}c=h1;
a=NULL;
p=p->
}returnh1;
}
3.2.3编译与调试
在VC++6.0的编译环境下,当程序编写完运行时,须先按F7,检查语法错误,之后按CTRL+F5运行程序,再根据程序运行结果进行调试,以优化程序。
在程序调试过程中,如果要对某个被调函数进行调试,可以标记该被调函数的某一句,之后按F10开始调试,如果不运行为标记的函数,可直接按F5,进行操作,进入标记过的函数之后,再逐句检查错误。
逐句调试程序时,可以根据watch等窗口查看指定变量的值,再根据程序需要改写程序,以避免出现栈溢出等错误。
4.
软件使用说明
4.1主界面介绍
打开程序进入主界面,出现项目编号,以及文字提示。
可根据个人需要输入项目编号,单机回车进入。
4.2创建学生信息数据表
在主界面输入“1”单击回车后即可进入穿件数据表界面。
然后根据提示信息输入学生信息,每个信息之间用空格(或回车符间隔开)。
结束输入后,系统自动返回学生信息数据表,并询问存储文件地址。
结束信息输入后,系统会提示,是否继续运行《学生成绩管理系统》,用户根据自己需要输入y或n,从而继续或退出程序。
4.3增加数据信息
界面与创建相似,都是按照用户需求逐一输入学生信息,信息输入结束后,系统自动返回学生信息数据表,并输出到屏幕上。
不同的是增加数据信息不会删除原有信息,而创建数据信息会返回新的链表表头,从而创建新的链表,而得到新的学生信息数据表。
4.4删除数据信息
在主界面选择项中,选择3.DELETE,进入删除功能。
按照提示信息,删除学生的学号。
程序自动删除后提示是否继续删除,否则,提示不存在,并询问是否继续删除。
4.5修改信息
修改信息是删除和增加的合成,功能与界面类似。
4.6查找信息
查找信息功能,分四个模块,分别是按学号,姓名,学院,班级查找。
根据提示信息进入相应模块,即可查询学生信息。
4.7统计功能
根据用户需要,分别包含平均分分数段统计,各科不及格率统计,最高分学生信息查询,以及按照总分排序等功能。
用户可以根据提示信息,进入相应功能模块并进行操作。
5.课程设计心得与体会
5.1概述
本次程序设计最大的收获主要有两点:
1.对数据库的创建及原理有了更进一步了解,2.对内存与指针更进一步了解。
5.2心得与体会
5.2.1数据库管理系统——链表+文件读写
数据库,是存放大量数据的地方,而现今最流行的数据库模型是关系型数据库。
所谓关系型数据库,就是存放具体信息的二维数据表,该二维表的行称为记录,列称为字段。
记录存放的是某个具体的对象,而字段存放的是对象所具有的属性。
联系链表的实质我们就可以发现:
其实,一个链表就是一个数据表,链表中的每一个节点就是数据表中的记录(对象),而链表的数据成员就是数据表记录(对象)中对应的字段(属性)。
因此,我们可以明白,其实链表就是要记录过个对象不同属性的一种变量类型。
而链表的操作过程都是在内存中完成的,不能存储到磁盘中,因此,就产生了另外一种C语言的功能:
文件读写。
文件读写,是将内存中得到的数据存储到磁盘中,以达到长期的数据存储和处理的目的。
这样,我们不难发现,其实,链表+文件读写就是简易的数据库管理系统(DBMS)。
自然,这也是学习链表和文件读写的根本目的。
因为,只有熟练掌握链表和文件读写,才能更好地进行数据挖掘,和数据开发,才能对大量数据进行高效率的处理。
5.2.2指针与内存
在刚开始学习C语言之时,我一直有一个疑问:
“为什么还要保留这种会造成内存溢出的指针概念?
”现在,我终于明白了!
指针变量,简称“指针”,其实就是存储内存地址的变量。
我们知道栈存储区为静态变量和形参分配内存空间,而堆存储区为函数动态分配内存。
而内存分配时其地址是随机的,比如0xcccccccc,而该数是超越内存大小的,是随机分配的,会导致内存溢出,无法进行程序。
因此,程序员必须清楚指针所指向的内存地址,否则会出现内存错误。
然而,即使指针会导致内存出错,也不能否定指针的作用。
因为,指针是联系程序和内存的关键,进行基础的内存操作时,必须使用指针。
譬如,将已建成的链表,以某个链表中的成员(属性)重新排序,就必须通过指针进行链表的重建。
指针是基础操作,而基础操作才是程序员的工作根本。
C语言是低级的高级语言,可以通过指针的使用,来操作内存。
因而,指针概念的保留是必然的。
6.参考文献
《程序设计基础(C语言)》
7.附录:
部分程序清单
#include"
stdio.h"
stdlib.h"
string.h"
#defineN100
intM=0;
//amountofstu
{
intnum;
charnam[N];
charcol[N];
charcla[N];
floatmath;
floateng;
floatclan;
floatsum;
floatave;
structnode*next;
#defineLsizeof(structnode)//thelengthofstructnode
//listthelinkmemberinformatin
voidlist(structnode*h)
structnode*p;
if(h==NULL)
puts("
Empty!
else
{
p=h;
Thestudent'
sInformation:
\nNo.\tName\tCollege\tClass\tMath\tEnglish\tC_lan\tTotal\tAve"
while(p!
=NULL)
{
printf("
%d\t%s\t%s\t%s\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\n"
p->
num,p->
nam,p->
col,p->
cla,p->
math,p->
eng,p->
clan,p->
sum,p->
ave);
p=p->
}
}
voidlist2(structnode*h)
\nTotal\tNo.\tName\tCollege\tClass\tMath\tEnglish\tC_lan\tAve"
%.2f\t%d\t%s\t%s\t%s\t%.2f\t%.2f\t%.2f\t%.2f\n"
//creatanewlinklist
structnode*creat(void)
structnode*h=NULL,*p,*q,*r;
charc='
y'
;
while(c=='
||c=='
Y'
)
Inputthestudent'
\nNumber\tName\tCollege\tClass\tMath\tEnglish\tC_language"
p=(structnode*)malloc(L);
M++;
scanf("
%d%s%s%s%f%f%f"
&
p->
num,&
nam,&
col,&
cla,&
math,&
eng,&
clan,&
sum,&
getchar();
p->
next=NULL;
floatsum,ave;
sum=p->
math+p->
eng+p->
clan;
ave=sum/3;
sum=sum;
ave=ave;
if(h==NULL)
h=p;
else
q=h;
while((p->
=NULL))
{
r=q;
q=q->
}
if(p->
num<
num)
{
if(q==h)
h=p;
else
r->
next=p;
p->
next=q;
else
q->
ContinueCREATornot?
(y/n)"
%c"
c);
getchar();
returnh;
//insertinformationintothecreated-linklist
structnode*insert(structnode*h)
structnode*p,*q,*r;
{
InsertInformation:
ContinueINSERTornot?
//deletetheinformation
structnode*del(structnode*h,intn)
structnode*p,*q;
p=h;
while((p->
q=p;
if(p->
num==n)
if(p==h)
h=p->
q->
free(p);
M--;
Can'
tDelete!
//modify
structnode*modify(structnode*h)
intn;
Whichstudent'
sinformationdoyouwanttomodify?
\nInputtheNo.:
scanf("
%d"
n);
h=del(h,n);
h=insert(h);
//searchtheinformationbynumber
structnode*sea_num(structnode*h)
InputtheStudent'
sNumber:
printf("
Error!
\nCan'
tFindtheStudent'
sNumber!
//searchtheinformationbyname
structnode*sea_nam(structnode*h)
struct