资源描述
内蒙古科技大学课程设计说明书
内蒙古科技大学
本科生课程设计说明书
题 目:C语言课程设计
—— 学生成绩管理系统
学生姓名:
学 号:
专 业:软件工程
班 级:1班
指导教师:
日 期:2015年 1月 1日
48
内蒙古科技大学课程设计任务书
课程名称
C语言课程设计
设计题目
学生成绩管理系统
指导教师
时间
2015.1.1-2015.1.7
一、教学要求
1. 巩固和加深学生对C语言课程的基本知识的理解和掌握
2. 掌握C语言编程和程序调试的基本技能
3. 利用C语言进行基本的软件设计
4. 掌握书写程序设计说明文档的能力
5. 提高运用C语言解决实际问题的能力
二、设计资料及参数
每个学生在教师提供的课程设计题目中任意选择一题,独立完成,题目选定后不可更换。
某班学生成绩管理,包括以下功能:
v 从键盘输入包括学号、姓名、各门课程成绩(不少于5门),并将其保存在磁盘文件里
v 打开文件后,计算每个人的总分和平均分,排序并保存
v 具有单项查询或多项查询的功能(即按照给定的关键字,如姓名找出满足条件的纪录)
v 具有插入、删除和修改功能
v 具有输出文件数据信息的功能
三、设计要求及成果
1. 分析课程设计题目的功能需求(可选用数组或链表实现,可多人(最多3人)协作完成一个题目)
2. 写出详细设计说明(至少包括功能实现分析和模块流程图)
3. 编写程序代码,调试程序使其能正确运行(代码书写要规范,标示符要见名知意,要有必要的注释,每人至少500行代码,不包括注释和花括号)
4. 设计完成的软件要便于操作和使用
5. 设计完成后提交课程设计报告(请严格按照模板进行排版)
四、进度安排
第一天 选择课程设计题目,分析课题的要求
第二天 编程
第三天 编程及调试
第四天 写课程设计报告
第五天 提交课程设计报告(打印稿及电子稿)
五、评分标准
1. 根据平时上机考勤、表现和进度,教师将每天点名和检查
2. 根据课程设计完成情况,必须有可运行的软件。
3. 根据课程设计报告的质量,如有雷同,则所有雷同的所有人均判为不及格。
六、建议参考资料
1.《C语言程序设计》,谭浩强,清华大学出版社
2.《C语言程序设计课程设计》,刘振安,机械工业出版社
目 录
内蒙古科技大学课程设计任务书 I
目 录 II
第一章 需求分析 3
1.1 引言 3
1.2 任务概述 3
1.3 数据描述 3
1.4 功能需求 4
1.5 性能需求 4
1.6 运行需求 5
1.7 任务计划 5
第二章 概要设计 6
2.1 总体设计 6
2.2 数据类型设计(或数据结构设计) 6
2.3 接口设计 7
2.4 运行界面设计 7
第三章 详细设计 8
3.1 输入模块设计 8
3.2 输出模块设计 10
3.3 查找模块设计 11
3.4 排序模块设计 14
3.5 保存及读取模块设计 16
第四章 测试分析 17
4.1 测试程序执行情况 17
4.2 出现的问题和解决的方法 20
第五章 课程设计总结 21
附录:程序代码 21
参考文献 46
第一章 需求分析
1.1 引言
此报告完整呈现了我开发“学生成绩管理系统”的整个软件过程,包括需求分析阶段,软件设计与实现阶段和测试阶段。在需求分析阶段,明确所要开发的软件应具有的功能、性能与界面,使系统使用人员及系统开发人员能清楚地了解用户的需求,并在此基础上进一步提出概要设计说明书和完成后续设计与开发工作。在软件设计与实现阶段,进一步细化软件设计阶段得出的软件总体概貌,把它加工成在程序细节上非常接近于源程序的软件表示,然后着手于实践。最后在测试阶段检验了我们的软件的实用性,发现了许多不足。这个报告即是对最后软件的总体描述
1.2 任务概述
学生成绩管理系统:
包括以下功能:
v 从键盘输入包括学号、姓名、各门课程成绩(不少于5门),并将其保存在磁盘文件里
v 打开文件后,计算每个人的总分和平均分,排序并保存
v 具有单项查询或多项查询的功能(即按照给定的关键字,如姓名找出满足条件的纪录)
v 具有插入、删除和修改功能
v 具有输出文件数据信息的功能
1.3 数据描述
数据是关于学生的资料:包括 学号、姓名、5门功课的成绩、总分、平均分。
1.4 功能需求
为实现学生成绩管理系统,该程序有以下功能:
1. 输入学生成绩。以插入节点的形式将输入的学生资料按总分降序插入链表中。
2. 删除学生成绩。用学号进行查找,查找到后直接删除。
3. 查询学生成绩。三种查找方式,1.姓名 2.学号 3.分数 。1.2.为精确查找,3为范围查找,输入成绩后,查找出所有高于该成绩的学生并输出。
4. 修改学生成绩。按学号查找学生,查找后可以修改学生的所有信息,包括学号。修改成绩后自动对总分、平均分更新。
5. 排序学生成绩。排序学生成绩有三种排序方案:1.学号升序。2.总分升序。3.总分降序
6. 保存学生成绩。将学生成绩保存到student 文件内,以便下次运行程序时读入数据。
7. 科目设置。对五门科目的名称进行设置。
8. 程序密码设置。程序首次运行时,设置密码。密码保存在mima.txt文件内。以后每次运行程序都需要输入密码。
9. 程序密码修改。在进入程序主界面后,可以对程序密码进行修改。修改密码会覆盖原有的mima.txt,将新的密码保存在该文件内。
10. 程序字体颜色。为了程序的美观性,在主菜单内设置了颜色功能。可以修改程序的颜色。有9种颜色可供选择。
1.5 性能需求
本程序采用动态内存申请的方式,储存学生成绩资料,尽可能的节省了所占内存空间,并且在程序结束时释放所有内存。
1.6 运行需求
在输入学号是学号数值大小不大于长整型的数值范围。
姓名不超过5个中文字符、11个英文字符。
学生成绩不超过宏定义的maxscore 100 不小于 minscore 0.
本程序在运行时,要求有student文件储存学生资料,mima.txt文件储存程序密码,kemu.txt文件储存科目名称。在文件不存在时,程序会自行创建这些文件以供使用。
1.7 任务计划
设计一个学生成绩管理系统,来管理学生成绩。
包括以下功能:
v 从键盘输入包括学号、姓名、各门课程成绩(不少于5门),并将其保存在磁盘文件里
v 打开文件后,计算每个人的总分和平均分,排序并保存
v 具有单项查询或多项查询的功能(即按照给定的关键字,如姓名找出满足条件的纪录)
v 具有插入、删除和修改功能
v 具有输出文件数据信息的功能
第二章 概要设计
2.1 总体设计
闪烁欢迎语
错三次
密码输入
结束程序
正确
从文件倒入数据
主菜单
0.结束程序
11.字体颜色设置
10.学生资料保存
9.科目设置
8.程序密码修改
7.排序学生资料
6.统计学生资料
5.显示学生资料
4.修改学生资料
3.查询学生资料
2.学生资料删除
1.学生资料输入
2.2 数据类型设计(或数据结构设计)
typedef struct student
{
long xuehao;
char name[12];
int chengji[N];
int zongfen;
float pingjun;
struct student*next;
} NODE;
2.3 接口设计
void huanyingyu(); //LED灯闪烁欢迎语
void mytime(); //输出问候语句+时间
void mima(char mi[],char mi1[]); //密码函数
void caidan(); //输出主菜单
NODE* daoru (NODE *l,char kemu [][20]); //已存在信息导入
void jieshu(NODE* l); //模块0 结束程序
NODE* InsertNode(NODE *head,char kemu [][20],int count);//模块1 插入学生资料 (总分排序)
NODE* DeleteNode(NODE* head); //模块2 删除学生资料
void FIND (NODE *head,char kemu [N][20] ); //模块3 查询学生资料
void xiugai(NODE *head,char kemu [N][20] ); //模块4 修改学生资料
void DisplyNode(NODE *head,char kemu [][20]); //模块5 显示学生资料
void Tongji(NODE* l,char kemu[][20]); //模块6 统计学生资料
NODE* paixv(NODE *head); //模块7 排列学生资料
void mimaxiugai(char* mi1); //模块8 密码修改
void kemushezhi(char kemu[][20],int k); //模块9 科目设置
void Save(NODE* l); //模块10 学生资料保存
void yanse(); //模块11 颜色设置
2.4 运行界面设计
第二章 详细设计
3.1 输入模块设计
1. 流程图
申请内存,建立节点
输入学号
是
学号是否雷同
若学号为0
否
继续输入其他信息
求总分、平均分
将该节点插入链表
返回主菜单
2.模块代码:
/* 函数功能:菜单功能1 输入学生信息 以总分降序插入链表*/
NODE *InsertNode(NODE *head,char kemu [][20],int count)
{
int j,i;
int sum,xuehao;
NODE *pr = head->next, *p = head, *temp = NULL,*q = head->next;
p = (NODE *)malloc(sizeof(NODE));/* 让p指向待插入节点 */
if (p == NULL) /* 若为新建节点申请内存失败,则退出程序 */
{
printf("No enough memory!\n");
exit(0);
}
p->next = NULL; /* 为待插入节点的指针域赋值为空指针 */
printf("请输入第%d位学生资料:",count);
printf("请输入学号:(输入0返回)");
scanf("%ld",&p->xuehao);
xuehao=p->xuehao;
if(p->xuehao==0)
{
free(p);
return head;
}
else
{
while (xuehao != q->xuehao && q->next != NULL)/* 未找到且未到表尾 */
{
q = q->next;
}
if (xuehao == q->xuehao)
{
printf("您输入的学好对应学生信息已存在,请检查是否错误后重新输入!\n");
free(p);
return head;
}
}
printf("请输入姓名:");
scanf("%s",p->name);
for(j=0; j<N; j++)
{
w:
printf("请输入%s的%s成绩:",p->name,kemu[j]);
scanf("%d",&p->chengji[j]);
if(p->chengji[j]>maxscore||p->chengji[j]<minscore)
{
printf("输入成绩超出有效范围,请重新输入!\n");
goto w;
}
}
sum = 0;
for(i=0; i<N; i++)
{
sum+=(*p).chengji[i];
}
p->zongfen = sum;
p->pingjun= (float)sum/N;
system("pause");
if (head == NULL) /* 若原链表为空表 */
{
head = p; /* 待插入节点作为头节点 */
}
else
{
/* 若未找到待插入节点的位置且未到表尾,则继续找 */
while (pr->zongfen > p->zongfen && pr->next != NULL)
{
temp = pr; /* 在temp中保存当前节点的指针 */
pr = pr->next;/* pr指向当前节点的下一节点 */
}//printf("程序运行到此");
if (pr->zongfen <= p->zongfen)
{
if (pr == head->next) /* 若在头节点前插入新节点 */
{
p->next = head->next;/* 将新节点的指针域指向原链表的头节点 */
head->next= p; /* 让head指向新节点 */
}
else /* 若在链表中间插入新节点 */
{
pr = temp;
p->next = pr->next;/* 将新节点的指针域指向下一节点 */
pr->next = p; /* 让前一节点的指针域指向新节点 */
}
}
else /* 若在表尾插入新节点 */
{
pr->next = p; /* 让末节点的指针域指向新节点 */
}
}
printf("学生资料添加成功!\n");
ziliao = 1;
return head; /* 返回插入新节点后的链表头指针head的值 */
}
3.2 输出模块设计
1. 流程图
传入链表头指针
是
是否为空链表
否
是
是否达到表尾
否
输出
返回主菜单
2.模块代码
/* 函数的功能:菜单更能5 显示学生资料 */
void DisplyNode(NODE *head,char kemu [N][20] )
{
NODE *p = head->next;
int j = 1;
printf("学号 姓名%8s%8s%8s%8s%8s 总分 平均分 编号\n",kemu[0],kemu[1],kemu[2],kemu[3],kemu[4]);
while (p != NULL) /* 若不是表尾,则循环打印 */
{
printf("%-13ld%-8s%-8d%-8d%-8d%-8d%-6d%-6.0d%-6.1f %-3d\n",p->xuehao,
p->name,
p->chengji[0],
p->chengji[1],
p->chengji[2],
p->chengji[3],
p->chengji[4],
p->zongfen,
p->pingjun,j);/* 打印第j个节点的数据 */
p = p->next; /* 让p指向下一个节点 */
j++;
}
}
3.3 查找模块设计
1. 流程图
1.学号查找 2.姓名查找 3.分数查找
3
2
1
分数是否大于查询分数
学号是否相等是否到表尾
姓名是否相同是否到表尾
否
否
否
进入下一个节点
进入下一个节点
是
是
输出
2.模块代码
/* 函数的功能:菜单功能3 查询学生资料 */
void FIND (NODE *head,char kemu [N][20] )
{
NODE *p = head->next;
int j = 1,k = 1,c=0;
long xuehao;
char name[20];
char c1[1];
int zongfen;
printf("请输出查找方式:\n1.学号查找\n2.姓名查找\n3.总分查找\n======>");
c1[0] = getche();
c = atoi(c1);
printf("\n");
if(c==1)
{
printf("请输入学号:");
scanf("%ld",&xuehao);
while (p != NULL) /* 若不是表尾,则循环打印 */
{
if(xuehao == p->xuehao)
{
if(k)
{
printf("学号 姓名%8s%8s%8s%8s%8s 总分 平均分 \n",kemu[0],kemu[1],kemu[2],kemu[3],kemu[4]);
}
printf("%-13ld%-8s%-8d%-8d%-8d%-8d%-6d%-6.0d%-6.1f \n",p->xuehao,
p->name,
p->chengji[0],
p->chengji[1],
p->chengji[2],
p->chengji[3],
p->chengji[4],
p->zongfen,
p->pingjun);/* 打印第j个节点的数据 */
k=0;
}
p = p->next; /* 让p指向下一个节点 */
}
if(k==1)
printf("抱歉,您查找的信息不存在!\n");
system("pause");
}
else if(c==2)
{
printf("请输入姓名:");
scanf("%s",name);
while (p != NULL) /* 若不是表尾,则循环打印 */
{
if(strcmp(name,p->name) == 0)
{
if(k)
{
printf("学号 姓名%8s%8s%8s%8s%8s 总分 平均分 \n",kemu[0],kemu[1],kemu[2],kemu[3],kemu[4]);
}
printf("%-13ld%-8s%-8d%-8d%-8d%-8d%-6d%-6.0d%-6.1f \n",p->xuehao,
p->name,
p->chengji[0],
p->chengji[1],
p->chengji[2],
p->chengji[3],
p->chengji[4],
p->zongfen,
p->pingjun);/* 打印第j个节点的数据 */
k=0;
}
p = p->next; /* 让p指向下一个节点 */
}
if(k==1)
printf("抱歉,您查找的信息不存在!\n");
system("pause");
}
else if(c==3)
{
printf("请输入要查找多少分以上的学生:");
scanf("%d",&zongfen);
while (p != NULL) /* 若不是表尾,则循环打印 */
{
if(zongfen <=p->zongfen)
{
if(k)
{
printf("学号 姓名%8s%8s%8s%8s%8s 总分 平均分 \n",kemu[0],kemu[1],kemu[2],kemu[3],kemu[4]);
}
printf("%-13ld%-8s%-8d%-8d%-8d%-8d%-6d%-6.0d%-6.1f \n",p->xuehao,
p->name,
p->chengji[0],
p->chengji[1],
p->chengji[2],
p->chengji[3],
p->chengji[4],
p->zongfen,
p->pingjun);/* 打印第j个节点的数据 */
k=0;
}
p = p->next; /* 让p指向下一个节点 */
}
if(k==1)
printf("抱歉,您查找的信息不存在!\n");
system("pause");
}
else
{
printf("输入有误,请重新输入!\n");
system("pause");
caidan();
printf("\n");
FIND (head,kemu);
}
}
3.4 排序模块设计
1. 流程图
1.升序排列 2.降序排列
1.按学号升序排序 2.按总分升序排序
1.按学号降序排列 2.按总分降序排列
返回主函数
调用显示资料函数
2.模块代码
/* 函数的功能:菜单功能7.1 学号升序排列学生*/
NODE* paixv(NODE* head)
{
NODE* r = head;
NODE* SL = NULL;
NODE* t,*cp,*ap;
char xv[1];
int xv1;
printf("请选择排序方式:\n1.学号升序排列\t\t2.总分升序排列\n3.总分降序排列\n");
xv[0] = getche();
xv1 = atoi(xv);
while (r != NULL)
{
t = r->next;
cp = SL;
ap = NULL;
while (cp != NULL)
{
if(xv1==1)
{
if(r->xuehao < cp->xuehao)
{
break;
}
else
{
ap = cp;
cp=cp->next;
}
}
else if(xv1==2)
{
if(r->zongfen < cp->zongfen)
{
break;
}
else
{
ap = cp;
cp=cp->next;
}}
}
if (ap == NULL)
{
r->next = SL;
SL = r;
}
else
{
r->next = cp;
ap->next = r;
}
r = t;
}
printf("排序完成!\n");
return SL;
}
3.5 保存及读取模块设计
1. 流程图
把本节点内容写入文件
释放内存
否
是否到表尾
是
返回主菜单
2. 模块代码
/* 函数功能:菜单功能10 对新录入的学生信息进行保存*/
void Save(NODE* l)
{
FILE *fp;
NODE *p;
int flag=1,count=0;
fp=fopen("student","w");
if(fp==NULL)
{
printf("\n=====>提示:重新打开文件时发生错误!\n");
exit(1);
}
p=l->next;
while(p!=NULL)
{ fprintf(fp,"%ld %s %d %d %d %d %d %d %f\n",p->xuehao,p->name,p->chengji[0],p->chengji[1],
p->chengji[2],p->chengji[3],p->chengji[4], p->zongfen, p->pingjun); p=p->next;count++;}
if(flag)
{printf("\n=====>提示:文件保存成功.(有%d条记录已经保存.)\n",count);
ziliao = 0;system("pause");}
fclose(fp);
}
第三章 测试分析
4.1 测试程序执行情况
1. 密码测试
先输入错误密码,在输入正确密码。
2. 输入学生资料测试
3. 查询学生成绩测试
4. 修改学生测试
5. 显示学生资料测试
6. 统计学生资料测试
7. 排序测试
8. 密码修改测试
9. 科目修改测试
10. 颜色更换测试
4.2 出现的问题和解决的方法
1.文件数据导入错误,导入后无法正确显示
解决方法:没有返回头指针,对daoru();函数添加了头指针的返回。
2.程序密码第一次输入错误后勿论之后输入的密码正确与否,都会提示密码错误
解决方法:第一次录入密码后没有对mi1[]数组进行清空,第二次输入的密码会不完全覆盖第一次输入的密码,在每一次判断密码是否正确后对mi1[]进行清空,这样之后录入的密码正确。
3.排序结果不正确
解决方法:排序时节点的交换出现问题,导致排序后的链表断点。更正交换代码后问题解决。
4.程序运行时如果把数字输入成字母,程序会崩溃
解决方法:对输入的数据进行判断,如果不是数字提示输入错误,重新录入。
5. 在修改信息函数中,修改学好,成绩这些用数组定义的量时没有问题可以正确修改,当修改库存数量和价格时会出现程序出错现象,而编译代码时并不提示有错,最后在仔细检查下终于发现是这2个地方忘了加取地址“&”,修改后程序可正确运
6.不存在文件时创建新文件后没有对头节点进行返回,导致其他功能不能正常运行。将头节点返回。
第四章 课程设计总结
该课程设计是进入大学以来的第一个课设,通过这次的课设,我对本学期所学内容有了更深层次的了解与认识,同时我感觉到了作为一个程序员的幸苦与智慧。就我本人而言,本次课程设计编写将尽两个月。
这次课程设计,我明白了对于编写程序,解题的思路尤为重要。在编写程序之前,如果没有比较清晰的思路,根本不可能编出好的程序。就算马马虎虎的编出来,程序的逻辑性、健壮性、完善性、合理性也不会很强。在编程之前,我们应反复研究题目要求,对题目涉及的情况进行比较充分的分析,以便编写出更加符合题意的程序;其次要充分考虑各种临界情况,对一些错误的输入进行处理。因此在我们编程序之前一定要做好充分的准备,首先要理清自己的思路,然后再将思路分划成几个模块,逐块的写好算法,最后再将所有的模块有机的联系起来,组成一个完整的程序。在成功通过编译的情况下,对程序运行的结果进行系统的分析,检验其正确性,如果有错误,应立即去分析源程序的逻辑错误,直到得到正确的结果。
附录:程序代码
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#include <windows.h>
#include <conio.h>
#define N 5
#define maxscore 100
#define minscore 0
int ziliao=0;
typedef struct student
{
long xuehao;
char name[12];
int chengji[N];
int zongfen;
float pingjun;
struct student*next;
} NODE;
void huanyingyu(); //LED灯闪烁欢迎语
void mytime(); //输出问候语句+时间
void mima(char mi[],char mi1[]); //密码函数
void caidan(); //输出主菜单
NODE* daoru (NODE *l,char kemu [][20]); //已存在信息导入
void jieshu(NODE* l); //模块0 结束程序
NODE* InsertNode
展开阅读全文