C语言程序设计课程设计.docx
《C语言程序设计课程设计.docx》由会员分享,可在线阅读,更多相关《C语言程序设计课程设计.docx(57页珍藏版)》请在冰豆网上搜索。
C语言程序设计课程设计
《C语言程序设计》课程设计
C课程设计作为一门课程设置,36学时。
根据较全面地覆盖C语言程序设计的实用内容和重点内容原则,设计了如下三道题目:
设计任务一应用结构数组处理学生信息
设计任务二应用单向链表处理学生信息
设计任务三应用随机二进制文件处理学生信息
C课程设计的程序规模较大,属于C综合应用,侧重C程序开发全过程的初步训练。
从基础实验过渡到课程设计,学生普遍感到无从下手。
我们采用模仿和引导、逐步过渡到独立设计的教学方法命题。
从命题入手,给定设计条件由细一点到粗一点的方法,引导学生应用结构化程序设计方法,开发规模较大的C程序。
设计任务一给出了程序总体设计、主控程序框架和部分函数,以及可执行的主控程序。
设计任务二给出了可执行的主控程序和部分函数。
设计任务三只给出原始数据和功能,程序设计全部由学生独立完成。
C实践教学环节的配合是较科学的,实施方法也是有效的,教学效果提高较快。
基础实验,一般能完成20到24题编程和调试。
课程设计共3题,一般能完成2题编程和调试,约15%~20%学生能完成全部设计任务。
大约有10%~15%学生,基础实验和课程设计都做得较差。
由于篇幅限制,本份材料只收集一份优秀的实验报告。
任务二应用单向链表处理学生信息
实验报告
——苏小聪
前言
在理论学习和基础实验的基础上,开发规模较大的程序,掌握应用计算机解决实际问题的基本方法,熟悉C程序开发的全过程。
本任务是根据给定的数据和程序,应用单向链表处理一个小班学生的信息。
通过整个程序开发的过程,提高综合应用C语言的能力、编程和调试能力,为学习软件专业课程创建较扎实的理论基础和实践基础。
一.系统功能和原始数据
⑴学生信息和数据格式
学生信息:
学生信息,包含:
学号,姓名,性别,出生日期(年,月,日),三门课成绩和总分(数
学,英语,C,总分)。
数据格式:
测试数据,以ASCII码文件studf.txt提供。
studf.txt文件结构:
学号姓名性别年月日数学英语C总分
studf.txt文件数据:
20015101张明男198210216072760
20015103李红英女198382510096890
20015102成杰男198311209570870
20015106许民光男19841267887740
20015104陈富来男198312158674920
20015107成杰男19841108478900
插入数据以ASCII码文件istudf.txt提供。
istudf.txt文件结构:
学号姓名性别年月日数学英语C总分
20015112成杰男198311209570870
20015109许民光男19841267887740
20015111陈富来男198312158674920_
⑵程序功能1)建立按学号递增的单向链表数据从ASCII码文件studf.txt读入2)显示学生信息3)插入若干学生 插入数据从ASCII码文件istudf.txt读入4)删除若干名学生 按学号查找需删除的学生信息5)按学号查学生分数和平均分数6)按姓名查学生分数和平均分数7)按总分查学生分数和平均分数8)查各门课程平均分9)查学生平均年龄10)查男女学生人数11)显示学生信息表
.程序总体设计
数据结构依据给定的学生信息和数据格式,链表结点必须用结构实现。
结构类型的层次结构:
structstudent学号字符串charno[9]姓名字符串charname[9](汉字)性别字符串charsex[3](汉字)出生日期日期结构structdate年intyear月intmonth日intday三门课成绩和总分整型数组intscore[4]结构类型定义为全局标识符:
structdate/*日期结构*/{intyear;/*年*/charmonth;/*月*/charday;/*日*/};structstudent/*学生信息结构*/{charno[9];/*学号*/charname[9];/*姓名*/charsex[3];/*性别*/structdatebirthday;/*出生日期*/intscore[4];/*三门课成绩和总分*/};
⑵模块划分依据程序的数据结构和功能,遵照“自顶向下”原则,采用基于函数的逐步求精法,描述该程
序的层次结构。
图1显示出该程序的层次结构,共三层。
图1程序的层次结构
函数原形清单:
11建立学生信息单向链表createstructstudent*create(structstudent*head,int*n)12按学号链表递增排序sort_lstructstudent*sort_l(structstudent*head)13插入学生信息structstudent*insert(structstudent*head,int*n)14按学号删除学生信息deletestructstudent*delete(structstudent*head,int*n)15按学号查学生信息和平均成绩srch_novoidsrch_no(structstudent*head)16按姓名查学生信息和平均成绩srch_namevoidsrch_name(structstudent*head)
17按总分查学生信息和平均成绩srch_tscore
voidsrch_tscore(structstudent*head)
18查各门课的平均分数find_ave
voidfind_ave(structstudent*head,intn)
19查学生的平均年龄find_age
voidfind_age(structstudent*head,intn)
1A查男女学生的人数find_pnum
voidfind_pnum(structstudent*head)
1B显示学生信息表printtable
voidprinttable(structstudent*head)
21显示学生信息printsi
voidprintsi(structstudent*head)
22显示插入或删除后的学生信息print_inf
voidprint_inf(structstudent*head)
⑶程序总体框架
模块层次结构,只确定了模块之间的关系和函数原型,不是程序的执行步骤。
程序总体框架是该程序的总体流程图。
该程序不是顺序连续地执行全部功能,而是在某一时刻有选择地执行一种或多种功能。
因此,选用菜单方式是较佳的方案。
程序总体框架如图2所示。
图2程序总体框架
程序组织
程序采用多源程序文件组织,由hstud_1.c主控源程序文件和stfun_1.c函数源程序文件组成。
三.功能块函数设计和调试
建立学生信息单向链表
函数原型、功能和形参说明
函数原型:
structstudent*create(structstudent*head,int*n)
函数功能:
建立学生信息单向链表
参数说明:
structstudent*head链表头结点指针
int*n学生人数指针
程序清单
structstudent*create(structstudent*head,int*n)
{
FILE*fp;
structstudent*p,*p1,*p2;
if((fp=fopen("studf.txt","r"))==NULL)
{
printf("不能打开studf.txt文件!
\n");
exit
(1);
}
while(!
feof(fp))
{
(*n)++;
p=(structstudent*)malloc(sizeof(structstudent));
fscanf(fp,"%s%s%s%d%d%d%d%d%d%d",
p->no,p->name,p->sex,
&p->birthday.year,&p->birthday.month,
&p->birthday.day,
&p->score[0],&p->score[1],&p->score[2],
&p->score[3]);
p->score[3]=p->score[0]+p->score[1]+p->score[2];
if(head==NULL)
{
head=p;
p1=p;
}
else
{
p1->next=p;
p2=p1;
p1=p;
}
}
p2->next=NULL;
free(p);
(*n)--;
fclose(fp);
returnhead;
}
运行结果
按学号链表递增排序
函数原型、功能和形参说明
函数原型:
structstudent*sort_l(structstudent*head)
函数功能:
按学号链表递增排序
参数说明:
structstudent*head链表头结点指针
程序清单
structstudent*sort_l(structstudent*head)
{
structstudent*phead,*p1,*p2,*p;
/*建立辅助结点*/
phead=(structstudent*)malloc(sizeof(structstudent));
phead->next=head;
head=head->next;
phead->next->next=NULL;
/*排序*/
while(head!
=NULL)
{
p2=phead;
p1=phead->next;
p=head;
head=head->next;
p->next=NULL;
while(strcmp(p->no,p1->no)>0&&p1!
=NULL)
{
p2=p1;p1=p1->next;
}
if(p1!
=NULL)
{
p->next=p1;p2->next=p;
}
else
p2->next=p;
}
head=phead->next;
free(phead);
returnhead;
}
运行结果
插入学生信息
函数原型、功能和形参说明
函数原型:
structstudent*insert(structstudent*head,int*n)
函数功能:
在已建立的链表中插入学生信息
参数说明:
structstudent*head链表头结点指针
int*n学生人数指针
程序清单
structstudent*insert(structstudent*head,int*n)
{
FILE*fp;
structstudent*p2,*p1,*p,*p3;
inti;
clrscr();
printf("插入前学生信息:
\n");
print_inf(head);
if((fp=fopen("istudf.txt","r"))==NULL)
{
printf("不能打开studf.txt文件!
\n");
exit
(1);
}
while(!
feof(fp))
{
p=(structstudent*)malloc(sizeof(structstudent));
fscanf(fp,"%s%s%s%d%d%d%d%d%d%d",
p->no,p->name,p->sex,
&p->birthday.year,&p->birthday.month,
&p->birthday.day,
&p->score[0],&p->score[1],&p->score[2],
&p->score[3]);
p->score[3]=p->score[0]+p->score[1]+p->score[2];
p->next=NULL;
p3=head;
i=0;
while(p3!
=NULL)
{
if(strcmp(p->no,p3->no)==0)
{
printf("%s该学生的记录已插入\n",p->name);
i++;
}
p3=p3->next;
}
if(i!
=0)
continue;
if(head==NULL)
head=p;
else
{
p1=head;
while(p1!
=NULL&&strcmp(p->no,p1->no)>=0)
{
p2=p1;
p1=p1->next;
}
if(p1==head)
{
p->next=head;
head=p;
}
elseif(p1!
=NULL)
{
p2->next=p;
p->next=p1;
}
else
p2->next=p;
}
(*n)++;
}
p2->next=NULL;
fclose(fp);
(*n)--;
printf("插入后的学生信息:
\n");
free(p);
print_inf(head);
returnhead;
}
运行结果
按学号删除学生信息
函数原型、功能和形参说明
函数原型:
structstudent*delete(structstudent*head,int*n)
函数功能:
在已建立的链表中按学号删除学生信息
参数说明:
structstudent*head链表头结点指针
int*n学生人数指针
程序清单
structstudent*delete(structstudent*head,int*n)
{
charno[9];
structstudent*p1=NULL,*p2;
clrscr();
printf("学生信息:
\n");
print_inf(head);
printf("输入删除学生的学号(以ctrl+z结束):
\n");
scanf("%s",no);
if(strcmp(no,"exit")==0)
returnhead;
while(!
feof(stdin))
{
if(head==NULL)
{
printf("空表!
\n");
returnhead;
}
else
{
p1=head;
while(p1!
=NULL&&strcmp(p1->no,no)!
=0)
{
p2=p1;
p1=p1->next;
}
if(p1==NULL)
printf("\n%s无此学号学生!
\n",no);
elseif(p1==head)/*删除头节点*/
{
head=p1->next;
free(p1);
(*n)--;
}
elseif(p1->next!
=NULL)/*删除中间节点*/
{
p2->next=p1->next;
free(p1);
(*n)--;
}
else/*删除尾节点*/
{
p2->next=NULL;
free(p1);
(*n)--;
}
}
scanf("%s",no);
p1=head;
}
printf("删除后的学生信息:
\n");
print_inf(head);
returnhead;
}
运行结果
按学号查学生信息和平均成绩
函数原型、功能和形参说明
函数原型:
voidsrch_no(structstudent*head)
函数功能:
按学号查学生信息和平均成绩
参数说明:
structstudent*head链表头结点指针
函数流程图
flagfor循环变量pwhile循环变量
程序清单
voidsrch_no(structstudent*head)
{
intfound,flag;
charno[9],ch;
structstudent*p;
for(flag=1;flag;)
{
found=0;
p=head;
printf("输入查找学生的学号:
");
scanf("%s",no);
printf("\n");
while(p!
=NULL)
{
if(strcmp(p->no,no)==0)
{
if(found==0)
printf("学号姓名性别年月日数学英语C总分平均分数\n");
printf("%-8s%-8s%-2s%4d%2d%2d%4d%4d%4d%5d%6.1f\n",
p->no,p->name,p->sex,
p->birthday.year,p->birthday.month,
p->birthday.day,
p->score[0],p->score[1],
p->score[2],p->score[3],
p->score[3]/3.0);
found=1;
}
p=p->next;
}
if(found==0)
printf("姓名:
%s未找到!
\n",no);
printf("继续查找[Y/N]:
");
getchar();
ch=getchar();
if((ch=='N')||(ch=='n'))
flag=0;
}
}
运行结果
按姓名查学生信息和平均成绩
函数原型、功能和形参说明
函数原型:
voidsrch_name(structstudent*head)
函数功能:
按姓名查学生信息和平均成绩
参数说明:
structstudent*head链表头结点指针
程序清单
voidsrch_name(structstudent*head)
{
intfound,flag;
charNAME[9],ch;
structstudent*p;
p=head;
for(flag=1;flag;)
{
found=0;
printf("输入查找学生的姓名:
");
scanf("%s",NAME);
printf("\n");
while(p!
=NULL)
{
if(strcmp(p->name,NAME)==0)
{
if(found==0)
printf("学号姓名性别年月日数学英语C总分平均分数\n");
printf("%-8s%-8s%-2s%4d%2d%2d%4d%4d%4d%5d%6.1f\n",
p->no,p->name,p->sex,
p->birthday.year,p->birthday.month,
p->birthday.day,
p->score[0],p->score[1],
p->score[2],p->score[3],
p->score[3]/3.0);
found=1;
}
p=p->next;
}
if(found==0)
printf("姓名:
%s未找到!
\n",NAME);
printf("继续查找[Y/N]:
");
getchar();
ch=getchar();
if((ch=='N')||(ch=='n'))
flag=0;
}
}
运行结果
按总分查学生信息和平均成绩
函数原型、功能和形参说明
函数原型:
voidsrch_tscore(structstudent*head)
函数功能:
按总分查学生信息和平均成绩
参数说明:
structstudent*head链表头结点指针
程序清单
voidsrch_tscore(structstudent*head)
{
intfound,SCORE,flag;
charch;
structstudent*p;
for(flag=1;flag;)
{
found=0,SCORE=0;
p=head;
printf("输入查找学生的总分:
");
scanf("%d",&SCORE);
printf("\n");
while(p!
=NULL)
{
if(SCORE==p->score[3])
{
if(found==0)
printf("学号姓名性别年月日数学英语C总分平均分数\n");
printf("%-8s%-8s%-2s%4d%2d%2d%4d%4d%4d%5d%6.1f\n",
p->no,p->name,p->sex,
p->birthday.year,p->birthday.month,
p->birthday.day,
p->score[0],p->score[1],
p->score[2],p->score[3],
p->score[3]/3.0);
found=1;
}
p=p->next;
}
if(foun