成绩管理系统

**

成绩管理系统

**

目录
1、问题定义 1
2、系统设计 1
2.1 总体设计 1
2.2 详细设计 3
2.2.1数据结构设计 3
2.2.2 主控main()函数执行流程 3
2.2.3输入记录模块 4
2.2.4查询记录模块 4
2.2.5更新记录模块 4
2.2.6统计记录模块 5
2.2.8函数功能描述 5
3、系统实现 8
3.1 编码 8
3.1.1 程序预处理 8
3.1.2 主函数main() 9
3.1.3 主菜单界面 11
3.1.4 表格形式显示记录 13
3.1.5查询学生记录 14
3.1.6 输入数据和增加学生记录 15
3.1.7删除学生记录 17
3.1.8 修改学生记录 19
3.1.9 统计学生成绩 20
3.1.10 排序学生记录 21
3.1.11 存储学生记录 23
3.1.12 读取文件中学生记录 24
3.2 测试与调试 26
3.2.1 概述 26
5、归纳总结 32
5.1 开发经验 32
5.2 实训中遇到的问题及解决方法 32
5.3 设计中尚存的不足之处 32
5.4 感想和心得体会 32
6、参考资料 33

学生成绩管理系统

本题目设计目的是训练学生的基本编程能力,了解管理信息系统的开发流程,熟悉C语言的文件的各种基本操作。本程序中涉及结构体、文件等方面的知识。通过本程序的训练,使学生能对C语言的文件操作有一个更深刻的了解,掌握利用文件存储结构实现对学生成绩管理的原理,为进一步开发出高质量的管理信息系统打下坚实的基础。

1、问题定义

创建一个学生成绩管理系统。假设系统中每个学生记录只包括学号、姓名、数学成绩、英语成绩、C语言成绩、总分、名次等信息。程序的运行效果如下图所示,选择任意菜单后,实现相应功能。

在问题定义阶段要考虑题目的可行性和需求分析,接下来进入开发阶段,完成系统设计和系统实现的任务。

2、系统设计

2.1 总体设计
采用模块化的程序设计方法,即将较大的任务按照一定的原则分为一个个较小的任务,然后分别设计各个小任务。需要注意的是划分出来的模块应该相对独立但又相关,且容易理解。可以用模块化层次结构图(即模块图)来分析其任务的划分,一般从上到下进行,最上面一层是主模块,下面各层是其上一层模块的逐步细化描述。
本成绩管理系统要求采用文件实现,如图2.1所示,它由如下五大功能模块组成:
 输入记录模块。完成将数据存入文件的工作。记录可以从以二进制形式存储的数据文件中读入,也可从键盘逐个输入学生记录。学生记录由学生的基本信息和成绩信息字段构成。当从数据文件中读入记录时,也就是把在以记录为单位存储的数据文件中,将记录逐条复制到文件中。
 查询记录模块。完成在文件中查找满足相关条件的学生记录。在此成绩管理系统中,用户可以按照学生的学号或姓名在文件中进行查找。若找到该学生的记录,则返回指向该学生的记录的指针。否则返回一个值为NULL的空指针,并打印出未找到该学生记录的提示信息。
 更新记录模块。完成对学生记录的维护。在此成绩管理系统中,它实现了对学生记录的修改、删除、插入和排序操作,并将修改后的数据存入源数据文件。
 统计记录模块。统计总分
 输出记录模块。一是实现对学生记录的存盘,即将记录写入数据文件中;二是实现将记录信息以表格的形式在屏幕上打印出来。

2.2 详细设计

2.2.1数据结构设计
 学生成绩信息结构体

struct student
{
	char num[30];//学号
    int zhuanye;     //专业
    int banji;      //班级
	char name[30];    //姓名
	int  cyuyan;           //C语言成绩
	int  shuxue;           //数学成绩
    int  yingyu;          //英语成绩
    float zongfen;      //总分
   };

结构体struct student将用于存储学生的基本信息,它将作为文件的数据域。为了简化程序,只取了3门成绩。
2.2.2 主控main()函数执行流程
本成绩管理系统执行主流程如图2.2所示。它先输出选择目录,然后根据目录选择。
若选择1,则调用input(stu)函数,执行输入操作;
若选择2,则调用output(stu)函数,执行输出操作;
若选择3,则调用lookfor(stu)函数,执行查询学生信息操作;
若选择4,则调用modify(stu)函数,执行修改学生信息操作;
若选择5,则调用delete_student(stu)函数,执行删除学生信息操作;
若选择6,则调用order(stu)函数,执行排序学生信息操作;
若选择7,则调用fileread(stu)函数,执行读取文件中学生信息操作;
若选择8,则调用filewrite(stu)函数,执行将学生记录存入数据文件的操作;
若选择9,则输出:“感谢你使用学生信息管理系统,请关掉程序”; 调用system(“pause”)函数输出:“按任意健继续执行”;关闭程序。
2.2.3输入记录模块
输入记录模块主要实现将数据存入struct student stu[N]中。当从数据文件中读出记录时,调用fread(&stu[j],sizeof(struct student),1,fp);文件读取函数,执行一次从文件中读取一条学生成绩记录信息存入struct student stu[N] 中的操作,并且该操作在fileread(stu)函数中执行,即当成绩管理系统进入选择7时,该操作执行了,若该文件中没有数据,系统会提示文件打开错误,程序无法进行,没有任何学生信息可操作。若用户应选择1,调用input(stu)函数,进行学生记录的输入,即完成将数据存入struct student stu[N]中添加操作。值得一提的是,这里的字符串和数值的输入分别采用了函数来实现,在函数中完成输入数据任务,并对数据进行条件判断,直到满足条件为止,这样一来,大大减少了代码的重复和冗余,符合模块化程序设计的特点。
2.2.4查询记录模块
查询记录模块主要实现了在struct student stu[N]中按学号或姓名查找满足相关条件的学生记录。在查询函数lookfor(stu)中,通过字符函数对已存入的学生信息进行比较,找出要查看的学生,输出到屏幕上。遵循模块化编程的原则。
2.2.5更新记录模块
此模块主要实现了对学生记录的修改、删除和排序操作。因为学生记录是以结构体形式存储的,所以这些操作都在结构体函数struct student stu[N]中完成。下面分别介绍着三个功能模块。
① 修改记录。该操作需要对结构体函数struct student stu[N]中成员的值进行修改。
第一步:利用函数strcmp( ),比较stu[j].num与xh,若相等返回值为0,则进行下一步。
第二步:再次确认是否修改。
第三步:选择要修改的课程,利用switch()函数修改成绩。
② 删除记录。该操作完成删除指定学号或姓名的学生记录。
第一步:利用函数switch() 判断是利用学号还是姓名查找学生记录。
第二步:利用 for () 循环进行删除。
③ 排序记录。有关排序的算法很多,如冒泡排序、插入排序等。我采用了选择排序的方法。
2.2.6统计记录模块
通过stu[count].zongfen=stu[count].cyuyan+stu[count].shuxue+stu[count].yingyu;计算出总成绩。
2.2.7输出记录模块
当把记录输出至文件时,调用filewrite(stu)函数,将已输入的学生信息写入文件。当把记录输出至屏幕时,调用output(stu)函数,将结构体函数struct student stu[N]中 的学生记录信息以表格的形式在屏幕上打印出来。
2.2.8函数功能描述
 system( )
函数原型:int system(char *command)
system( ) 函数是C函数库stdlib.h、process.h中的一个函数。system(“pause”)可以实现冻结屏幕,便于观察程序的执行结果;system(“cls”)可以实现清屏操作。而调用color函数可以改变控制台的前景色和背景, 调用system(“mode con cols=列数 lines=行数”)函数可以调节控制台的宽度和高度。
例如: system(“pause”); //程序暂停
 system(“cls”); //清屏语句
system(“mode con:cols=150 lines=30”) //调节控制台的宽度和高度
system(“color 1b”) //调节控制台的背景和字体颜色
用 system(“color1b”) 其中color后面的1是背景色代号,b是前景色代号。各颜色代码如下:
0=黑色 1=蓝色 2=绿色 3=湖蓝色 4=红色 5=紫色 6=黄色 7=白色 8=灰色 9=淡蓝色 A=淡绿色 B=淡浅绿色 C=淡红色 D=淡紫色 E=淡黄色 F=亮白色
 goto point1 实现输入错误次数过多,程序跳转重新开始
 fflush(stdin);
函数原型:int fflush(FILE *stream)
fflush(stdin)功能: 清除文件缓冲区,文件以写方式打开时将缓冲区内容写入文件。
 switch (choice) //根据选择,调用不同的函数来完成不同的任务
函数原型:switch ( 常量表达式 )
{
case 常量1 :语句;
case 常量2 :语句;
case 常量3 :语句;

case 常量n:语句;
default :语句;
}
switch (choice) 功能:根据选择,调用不同的函数来完成不同的任务
 return();
return;的作用相当于break;用于中断循环的作用;
return 0;则是return的另一种用法,专用于返回值非void的函数返回其值。
 do-while
do-while 循环语法 格式:
do
{
循环体;
}
while (条件表达); //条件表达,可以引用外传感器返回值。
以上循环将先运行一次,因为经过第一次do循环后,当检查条件表达式的值时,其值为 不成立时而会退出循环。保证了至少执行do{ }内的语句一次。
在本程序中实现返回控制台的操做和提示输入位数为一确定数。
 for(单次表达式;条件表达式;末尾循环体)
{
中间循环体;
}
在本程序中实现循环控制输出的个数。
 strcmp(stu[j].num,xh)0)
函数原型:extern int strcmp(const char *s1,const char *s2);
当s1<s2时,返回为负数;
当s1
s2时,返回值= 0;
当s1>s2时,返回正数。
即:两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇’\0’为止。
在本程序中实现通过字符函数对已存入的学生信息进行比较,找出要查看的学生
 FILE *fp;
FILE *fp 是声明,声明fp是指针,用来指向FILE类型的对象。*fp是指向文件结构体的指针变量,通过fp可找到存放某个文件信息的结构变量,根据这个结构变量的信息找到该文件,实施对文件的操作。fp通常被成为一个指向文件的指针。
 fread(&stu[j],sizeof(struct student),1,fp);
fwrite(&stu[j],sizeof(struct student),1,fp);
函数原型:size_t fread ( void *buffer, size_t size, size_t count, FILE *stream) ;
参 数:buffer用于接收数据的内存地址,size要读的每个数据项的字节数,单位是字节,count要读count个数据项,每个数据项size个字节.,stream输入流。
在本程序中实现写入文件和读取文件。
 主函数main()
整个成绩管理系统控制部分,其详细说明可参考图二。
完成在上述系统设计后,即可着手进行系统实现的工作,开始程序代码的编写。

3、系统实现

3.1 编码
3.1.1 程序预处理
包括加载头文件,定义结构体、常量和变量,并对它们进行初始化工作。

#include"stdio.h"        //标准的输入输出函数文件头部说明
#include"math.h"        //数学出函数文件头部说明
#include"ctype.h"        //字符函数文件头部说明
#include"string.h"        //字符串函数文件头部说明
#include"stdlib.h"    //通过该函数头部里的函数,改变控制台的背景和颜色
#include"windows.h"    //头文件声明,下文用到了改变控制台的宽度和高度
#define N 1000            //宏定义说明
struct student
{
	char num[30];//学号
    int zhuanye;     //专业
    int banji;      //班级
	char name[30];    //姓名
	int  cyuyan;           //C语言成绩
	int  shuxue;           //数学成绩
    int  yingyu;          //英语成绩
    float zongfen;      //总分
   };
//****************************************函数的声明********************************************
void input(struct student stu[N]);     //输入函数
void output(struct student stu[N]);     //各类用户自定义函数的声明
void lookfor(struct student stu[N]);    //查询函数
void modify(struct student stu[N]);     //修改函数
void order(struct student stu[N]);     //排序函数
void delete_student(struct student stu[N]);   //删除函数
void xuehao(struct student stu[N]);    //自定义通过学号方式删除学生信息函数  
void xingming(struct student stu[N]);   //自定义通过姓名方式删除学生信息函数
void fileread(struct student stu[N]);	//读取文件信息函数定义
void filewrite(struct student stu[N]);   //写入文件函数定义
int  count=0;;
struct student t;
3.1.2 主函数main()
main()函数主要实现了对整个程序的运行控制,以及相关功能模块的调用。详细分析可参考图2main() 
{
    struct student stu[N];  
	int choice;
	int sum;
	system("mode con:cols=150 lines=30");        //调节控制台的宽度和高度
	 system("color 1b");      //调节控制台的背景和字体颜色
	 sum=0;
point1: 
	do 
	{	printf("\t\t\t\t\t\t\t -------------------------------------------------\n");
	    printf("\t\t\t\t\t\t\t +		学生成绩管理系统			+\n");
     	printf("\t\t\t\t\t\t\t -------------------------------------------------\n");
	     printf("\t\t\t\t\t\t\t\t\t ***************\n");
	      printf("\t\t\t\t\t\t\t\t\t1、添加学生信息\n");
        	printf("\t\t\t\t\t\t\t\t\t2、浏览学生信息\n");
	         printf("\t\t\t\t\t\t\t\t\t3、查询学生信息\n");
	           printf("\t\t\t\t\t\t\t\t\t4、修改学生信息\n");
            	printf("\t\t\t\t\t\t\t\t\t5、删除学生信息\n");
	             printf("\t\t\t\t\t\t\t\t\t6、排列学生信息\n"); 
                  printf("\t\t\t\t\t\t\t\t\t7、读取文件学生\n");					//从文件读取
	               printf("\t\t\t\t\t\t\t\t\t8、保存到文件\n");					 //保存到文件
	                printf("\t\t\t\t\t\t\t\t\t9、退出系统\n");   
	                 printf("\t\t\t\t\t\t\t\t\t***************\n"); 
	                  printf("\t\t\t\t\t\t\t请输入你的选择:\n");
	               scanf("%d",&choice);
	fflush(stdin);       //清除输入缓冲区
	if (choice>9||choice<=0)
	{
	sum++;
	if (sum>=5)
	{
	printf("输入错误次数过多,程序将重新开始\n");
	system("pause");        //程序暂停
	system("cls");   //清屏语句
	goto point1;
	}
	}
	switch (choice)       //根据选择,调用不同的函数来完成不同的任务
	{
	case 1:input(stu);break;       //自定义输入函数 
	case 2:output(stu);break;       //自定义输出函数
	case 3:lookfor(stu);break;      //自定义查询学生信息函数
	case 4:modify(stu);break;      //自定义修改函数
	case 5:delete_student(stu);break;  //自定义删除函数
	case 6:order(stu);break;           //排序函数的定义
	case 7:fileread(stu);break;	     //读取文件信息函数定义
	case 8:filewrite(stu);break;    //写入文件函数定义
	case 9:printf("感谢你使用学生信息管理系统,请关掉程序!!!\n");system("pause");break;
	default:printf("无效的选择!!!请重新输入!!!\n");break;
	}
	}while (choice!=9);
	printf("the program is over!!!\n");
	 return 0;
}
3.1.3 主菜单界面
用户进入成绩管理系统时,需要显示主菜单,提示用户进行选择,完成相应任务。此代码被main()函数调用。
point1: 
	do 
	{	printf("\t\t\t\t\t\t\t -------------------------------------------------\n");
	    printf("\t\t\t\t\t\t\t +		学生成绩管理系统			+\n");
     	printf("\t\t\t\t\t\t\t -------------------------------------------------\n");
	     printf("\t\t\t\t\t\t\t\t\t ***************\n");
	      printf("\t\t\t\t\t\t\t\t\t1、添加学生信息\n");
        	printf("\t\t\t\t\t\t\t\t\t2、浏览学生信息\n");
	         printf("\t\t\t\t\t\t\t\t\t3、查询学生信息\n");
	           printf("\t\t\t\t\t\t\t\t\t4、修改学生信息\n");
            	printf("\t\t\t\t\t\t\t\t\t5、删除学生信息\n");
	             printf("\t\t\t\t\t\t\t\t\t6、排列学生信息\n"); 
       printf("\t\t\t\t\t\t\t\t\t7、读取文件学生\n");	//从文件读取
	    printf("\t\t\t\t\t\t\t\t\t8、保存到文件\n");		//保存到文件
	                printf("\t\t\t\t\t\t\t\t\t9、退出系统\n");   
	                 printf("\t\t\t\t\t\t\t\t\t***************\n"); 
	                  printf("\t\t\t\t\t\t\t请输入你的选择:\n");
	               scanf("%d",&choice);
	fflush(stdin);       //清除输入缓冲区
	if (choice>9||choice<=0)
	{
	sum++;
	if (sum>=5)
	{
	printf("输入错误次数过多,程序将重新开始\n");
	system("pause");        //程序暂停
	system("cls");   //清屏语句
	goto point1;
	}
	}
	switch (choice)       //根据选择,调用不同的函数来完成不同的任务
	{
	case 1:input(stu);break;       //自定义输入函数 
	case 2:output(stu);break;       //自定义输出函数
	case 3:lookfor(stu);break;      //自定义查询学生信息函数
	case 4:modify(stu);break;      //自定义修改函数
	case 5:delete_student(stu);break;  //自定义删除函数
	case 6:order(stu);break;           //排序函数的定义
	case 7:fileread(stu);break;	     //读取文件信息函数定义
	case 8:filewrite(stu);break;    //写入文件函数定义
	case 9:printf("感谢你使用学生信息管理系统,请关掉程序!!!\n");system("pause");break;
	default:printf("无效的选择!!!请重新输入!!!\n");break;
	}
	}while (choice!=9);
	printf("the program is over!!!\n");
	 return 0;
3.1.4 表格形式显示记录
由于记录显示操作经常进行,所以将这部分由独立的函数来完成,减少代码的重复。它将显示文件中存储的学生记录,内容为student结构中定义的内容。
void output(struct student stu[N])     //自定义输出函数
{
	int j;
	system("cls");
  if (count==0)
	{
	printf("当前已存学生信息为0个\n");
	return;
	}
	for (j=0;j<count;j++)
	{
	printf("学号\t\t姓名\t\t专业\t\t班级\t数学\t英语\tC语言\t\t总分\n");
	for (j=0;j<count;j++)           //for循环控制输出的个数
	{                            
	printf("%s\t",stu[j].num);
	printf("%s\t\t",stu[j].name);
    if (stu[j].zhuanye==1)  printf("计算机科学\t");
    	else
         printf("网络工程\t");      
	printf("%d\t",stu[j].banji);
	printf("%d\t",stu[j].shuxue);
	printf("%d\t",stu[j].yingyu);
	printf("%d\t\t",stu[j].cyuyan);
    printf("%f\t\t\n",stu[j]. zongfen);
	}
	}
}
3.1.5查询学生记录
当用户执行此查询任务时,系统会提示用户进行查询字段的选择,即按学号或姓名进行查询。若此学生记录存在,则会打印输出此学生记录的信息。void lookfor(struct student stu[N])                   //自定义查询学生信息函数
{
	int j,flag=0;
	char xh[25];
	system("cls");
    if (count==0)
	{
	printf("当前已存学生信息为0个,无法查询!!!\n");
	return;
	}
	else
	{
	printf("请输入你想要查看的同学学号\n");
	scanf("%s",&xh);
	fflush(stdin);  //清除缓冲区
	for (j=0;j<count;j++)
	{
	if (strcmp(stu[j].num,xh)==0)       //通过字符函数对已存入的学生信息进行比较,找出要查看的学生
	{
	printf("学号\t\t姓名\t\t专业\t\t班级\t数学\t英语\tC语言\t\t总分\n");
	printf("%s\t",stu[j].num);
	printf("%s\t\t",stu[j].name);
    if (stu[j].zhuanye==1)  printf("计算机科学\t");
    	else
         printf("网络工程\t");      
	printf("%d\t",stu[j].banji);
	printf("%d\t",stu[j].shuxue);
	printf("%d\t",stu[j].yingyu);
	printf("%d\t\t",stu[j].cyuyan);
    printf("%f\t\t\t\n",stu[j]. zongfen);
	}
	if(j==count)
	printf("很抱歉,没有你所需要的学生信息\n");
}

	}

	}
3.1.6 输入数据和增加学生记录
在此成绩管理系统中,要求用户输入的只有字符型和数值型数据,所以设计了下面这个函数来单独处理,并对输入的数据进行检验。
void input(struct student stu[N])      //自定义输入函数
{
	int len;
	system("cls");
    printf("请添加要输入学生的信息\n");
	do {
	printf("请输入由10位数字组成的学生学号\n");   //do-while循环应用,提示输入位数为一确定数
	scanf("%s",&stu[count].num);
	len=strlen(stu[count].num); //计数
	}while(len!=10);
	printf("请输入所需要的专业代号:1、计算机科学 2、网络工程\n");  //采用如此方法解决了专业输入难问题
	scanf("%d",&stu[count].zhuanye);
    printf("请输入对应的学生班级号码:1、18511 2、18514 \n");
	scanf("%d",&stu[count].banji);
	printf("请输入同学的姓名\n");
	scanf("%s",stu[count].name);									
   do {
	printf("请输入不大于100的学生各科成绩\n");
	printf("C语言成绩:");
	scanf("%d",&stu[count].cyuyan);
	printf("数学成绩:");
	scanf("%d",&stu[count].shuxue);
	printf("英语成绩:");
	scanf("%d",&stu[count].yingyu);
   }while(stu[count].cyuyan>100||stu[count].shuxue>100||stu[count].yingyu>100);//同上同上
     stu[count].zongfen=stu[count].cyuyan+stu[count].shuxue+stu[count].yingyu;   //总分
    count++;
	}
3.1.7删除学生记录
在删除操作中,系统会按用户要求先找到该学生记录,然后从文件中删除该条数据。
void delete_student(struct student stu[N])        //自定义删除函数
{
	int choice;
	system("cls");
	if (count==0)
	{
	printf("当前已存学生信息为0个,无法删除!!!\n");
	return;
	}
	else
	{
	printf("请选择你所要删除的方式:1、学号 2、姓名(如果你的姓名是中文,那么无法删除,请选择学号删除) 3、取消\n");
	scanf("%d",&choice);
	switch(choice)            //switch语句对用户要删除的方式进行选择
	{
	case 3:return;break;
	case 2:xingming(stu);break;         //用户自定义函数之间的套用
	case 1:xuehao(stu);break;
	default:printf("无效的选择!!!请重新输入!!!\n");break;
	}
	}
}
void xuehao(struct student stu[N])           //自定义通过学号方式删除学生信息函数
{
	int j,index=0,k=count;
	char xh[25];
	system("cls");
	printf("请输入你想要删除的同学学号\n");
	scanf("%s",xh);
	fflush(stdin);
	for (j=0;j<count;j++)
	{ if (strcmp(stu[j].num,xh)==0)
	{	
	for (j=index;j<count;j++)
	stu[j]=stu[j+1];
	count--;
	if (count<k)
	printf("你已经删除成功\n");
	}
	index++;}
	if (j==count)
	printf("抱歉!!!没有你所需要删除的学生信息!*_*!\n");
}
void xingming(struct student stu[N])           //自定义通过姓名方式删除学生信息函数
{
	int flag=0,j,k=count;
	char xm[25];
	system("cls");
	printf("请输入你想要删除的同学姓名\n");
	scanf("%s",xm);
	fflush(stdin);
	for (j=0;j<count;j++)
	{
	if (strcmp(stu[j].num,xm)==0)
	{
 
	for (j=flag-1;j<count;j++)             
	stu[j]=stu[j+1];
	count--;
	if (count<k)
	printf("你已经删除成功\n");
	}	
	flag++;}
	if (j==count)
	printf("抱歉!!!没有你所需要删除的学生信息!*_*!\n");
}
3.1.8 修改学生记录
在修改学生记录操作中,系统会先按输入的学号查询到该记录,然后提示用户选择要的修改课程,然后对学生成绩修改。
void modify(struct student stu[N])    //自定义修改函数
{
	int j,flag=0,course;
	char xh[25];
	system("cls");
	if (count==0)
	{
	printf("当前已存学生信息为0个,无法修改!!!\n");
	return;
	}
	else
	{
	printf("请输入你想要修改的同学学号\n");
	scanf("%s",&xh);
	fflush(stdin);
	for (j=0;j<count;j++)
	if (strcmp(stu[j].num,xh)==0)   //比较stu[j].num与xh若相等返回值为0     
	{
	printf("你确定要修改学生的信息吗???如果不确定的话,请关掉本程序吧!!!\n");
	printf("选择课程: 1、数学 2、英语 3、C语言\n ");
	scanf("%d",&course);
	printf("请输入你想要修改后的学生成绩\n");
	switch(course)
	{
	case 1:scanf("%d",&stu[j].shuxue);break;
	case 2:scanf("%d",&stu[j].yingyu);break;        //switch控制语句
	case 3:scanf("%d",&stu[j].cyuyan);break;
	default:printf("无效的选择!!!请重新输入!!!\n");break;
	} 
	}
	}
}
3.1.9 统计学生成绩
统计学生成绩,保存到文件中。可在浏览和查询学生信息中输出。
此功能有输入函数完成。
void input(struct student stu[N])      //自定义输入函数
{
	int len;
	system("cls");
    printf("请添加要输入学生的信息\n");
	do {
	printf("请输入由10位数字组成的学生学号\n");   //do-while循环应用,提示输入位数为一确定数
	scanf("%s",&stu[count].num);
	len=strlen(stu[count].num); //计数
	}while(len!=10);
	printf("请输入所需要的专业代号:1、计算机科学 2、网络工程\n");  //采用如此方法解决了专业输入难问题
	scanf("%d",&stu[count].zhuanye);
    printf("请输入对应的学生班级号码:1、18511 2、18514 \n");
	scanf("%d",&stu[count].banji);
	printf("请输入同学的姓名\n");
	scanf("%s",stu[count].name);									
   do {
	printf("请输入不大于100的学生各科成绩\n");
	printf("C语言成绩:");
	scanf("%d",&stu[count].cyuyan);
	printf("数学成绩:");
	scanf("%d",&stu[count].shuxue);
	printf("英语成绩:");
	scanf("%d",&stu[count].yingyu);
   }while(stu[count].cyuyan>100||stu[count].shuxue>100||stu[count].yingyu>100);//同上同上
     stu[count].zongfen=stu[count].cyuyan+stu[count].shuxue+stu[count].yingyu;   //总分
    count++;
	}
3.1.10 排序学生记录
在排序学生记录操作中,系统会利用选择排序法实现成绩的降序排序,并记录结果。
void order(struct student stu[N])        //排序函数的定义
{
	int j,k,choice,index;
	system("cls");
	printf("请输入你想要进行排序的方式(所有排序的方式均是降序)!!!\n");
	printf("1、数学 2、英语 3、C语言4、总分\n");
	scanf("%d",&choice);
	switch (choice)
	{
	case 1:for (j=0;j<count;j++)
    { index=j; 
	for (k=j+1;k<count;k++)
    if (stu[k].shuxue>stu[index].shuxue)
    {t=stu[k];stu[k]=stu[index];stu[index]=t;}
     };break;
	case 2:for (j=0;j<count;j++)
     { index=j; 
	for (k=j+1;k<count;k++)
    if (stu[k].yingyu>stu[index].yingyu)
{t=stu[k];stu[k]=stu[index];stu[index]=t;}		
//整个为排序部分,采用了选择排序的方法
     };break;
	case 3:for (j=0;j<count;j++)
     { index=j; 
	for (k=j+1;k<count;k++)
    if (stu[k].cyuyan>stu[index].cyuyan)
    {t=stu[k];stu[k]=stu[index];stu[index]=t;}
     };break;
    case 4:for (j=0;j<count;j++)
     { index=j; 
	for (k=j+1;k<count;k++)
    if (stu[k]. zongfen>stu[index]. zongfen)
    {t=stu[k];stu[k]=stu[index];stu[index]=t;}   
     };break;
	default:printf("无效的选择!!!请重新输入!!!\n");break;
	}
}
3.1.11 存储学生记录
在存储学生记录操作中,系统会将数据写入磁盘数据文件中。
void filewrite(struct student stu[N])					//写入文件函数定义
{
	int j=0;
	char c;
	FILE *fp;
	printf("请选择是否要存入已输入的学生信息:'y'还是'n'???\n");
	scanf("%c",&c);
	fflush(stdin);
	while(c!='y'&&c!='n'){
	if (c!='y'&&c!='n')
	printf("输入错误,请重新输入\n");
	printf("以下操作将会覆盖已存储的数据,确定请输入'y'或'n'???\n");
	scanf("%c",&c);
	fflush(stdin);
	}
	if (c=='y')
	{
	if((fp=fopen("d:\\stu.dat","wb"))==NULL)
	{
		printf("文件打开错误,程序无法进行\n");
		exit(0);
	}
	for(j=0;j<count;j++)
	  {fwrite(&stu[j],sizeof(struct student),1,fp);
	}
	fclose(fp);//关闭文件
	if(count==0)
		printf("没有文件,无法保存\n");
	else
	printf("数据存储完毕\n");
	system("pause");
	}
	else
		return;
}
3.1.12 读取文件中学生记录
在存储有学生记录的文件数据,读取到系统中。
void fileread(struct student stu[N])					//读取文件信息函数定义
{
	int j=0;
	char c;
	FILE *fp;
	system("cls");
	printf("请选择是否要读取文件的学生信息:'y'还是'n'???\n");
	scanf("%c",&c);
	fflush(stdin);
	while(c!='y'&&c!='n')
	{
	if (c!='y'&&c!='n')
	printf("输入错误,请重新输入\n");
	printf("以下操作将会覆盖已存储的数据,确定请输入'y'或'n'???\n");
	scanf("%c",&c);
	fflush(stdin);
	}
	if (c=='y')
	{
	if((fp=fopen("d:\\stu.dat","rb"))==NULL)
	{
		printf("文件打开错误,程序无法进行\n");
		exit(0);
	}
	fread(&stu[j],sizeof(struct student),1,fp); 
	count=0;
	count++;
	j++;
	while(fread(&stu[j],sizeof(struct student),1,fp))
	{
		j++;
		count++;
	}
	fclose(fp);
	printf("数据读取完毕!!!\n");
	system("pause");  //就是暂停程序的执行,等待任意健继续执行。
	}
	else
	return;  //c=n
}

3.2 测试与调试

3.2.1 概述
一般情况下,为解决一个问题所编写的程序代码较长,可能包括几百条甚至成千上万条语句。在检查并排除所有语法错误后,还会有不易发现的逻辑错误,因此要对程序进行认真仔细的测试与调试。
测试是通过运行程序发现错误的过程,常见的错误有数据溢出、数组越界、进入死循环、语句顺序颠倒、多加“;”或少加“{}”等等。调试则是确定测试中找到的错误性质并改正错误的过程。测试与调试通常交替进行,即测试——调试——再测试——再调试。
能检查出尚未发现的、各种不同类型错误的测试才是成功的测试。测试程序需要测试用例,测试用例可用如下公式表示:测试用例=测试数据+预期结果。
好的测试用例应该是用尽可能少的测试数据发现尽可能多的错误,即发现错误的概率要大。要选择合适的测试数据,使系统在运行时尽量能执行到每条语句,以测试各指令是否正确。还应分别测试输入合法数据与非法数据时,程序的运行情况,。对于合法数据,还要考虑数据的一般性与特殊性,如求最大值的问题,应测试最大值在最前面、最后面、中间某一位置的情况。
测试可按模块测试、组装测试和确认测试的步骤进行。
(1)模块测试就是分别对各模块进行测试的过程。在编写一个模块后应立即对其进行测试,因为这时对模块记忆深刻,而且单个模块相对较小,所以容易构造测试数据,能方便地检查和改正错误。
(2)组装测试就是把所有模块(应该是通过模块测试的模块)按预先制定的计划逐步组装和测试的过程。一般情况下,各模块之间要相互传递数据和控制信息,因此组装测试的主要任务是发现模块接口中的错误。
(3)确认测试是最后一个步骤,一般在将软件交付用户之前,应确认软件是否确实满足用户的要求,通常使用接近实际的用例进行测试。
测试程序时,用监视窗口可以随时查看变量或表达式的值,有时还可以将部分程序代码用注释符暂时括起来,缩短程序,以便压缩出错代码的范围。
1.调试命令
我们也可以在 VC“Build”(组建)菜单下的“Start Debug”(开始调试)中点击 Go(F5)命令进入调试状态,Build 菜单自动变成 Debug 菜单,提供以下专用的调试命令:
Go(F5) 从当前语句开始运行程序,直到程序结束或断点处。
Step Into(F11) 单步执行下条语句,并跟踪遇到的函数。
Step Over(F10) 单步执行(跳过所调用的函数)
Run to Cursor(Ctrl+F10) 运行程序到光标所在的代码行。
Step out(Shift+F11) 执行函数调用外的语句,并终止在函数调用语句处。
Stop Debugging(Shift+F5) 停止调试,返回正常的编辑状态
必须在运行程序时用 Go 命令(而不是 Execute)才能启动调试模式。在调试模式下,程序停止在某条语句,该条语句左边就会出现一个黄色的小箭头。我们随时中断程序、单步执行、查看变量、检查调用情况。比如,按“F5”功能键进入调试模式,程序运行到断点处暂停;不断按“F10”功能键,接着一行一行地执行程序,直到程序运行结束。
需要说明的是,如果希望能一句一句地单步调试程序,在编写程序时就必须一行只写一条语句。
2.察看变量
单步调试程序的过程中,我们可以在下方的Variables (变量)子窗口和Watch(监视) 子窗口中动态地察看变量的值,如图 1-11 所示。Variables 子窗口中自动显示当前运行上下文中的各个变量的值变量,而 Watch 子窗口内只显示在此 Watch 子窗口输入的变量或表达式的值。随着程序的逐步运行,也可以直接用鼠标指向程序中变量查看其值。例如在图 1-11 中,我们可以清楚地看到,程序已经为自动型变量 first、second、big 分配了内存,但它们的初始值是随
机的。
Variables 子窗口有 3 个选项卡:Auto、Locals 和 This。
Auto 选项卡: 显示出当前语句和上一条语句使用的变量,它还显示使用 Step over 或 Step out 命令后函数的返回值。
Locals 选项卡:显示出当前函数使用的局部变量。
This 选项卡: 显示出由 This 所指向的对象(C 语言不用 this)。
如果变量较多,自动显示的Variables 窗口难以查看时,还可以在右边的Watch 子窗口中添加想要监控的变量名。例如,图 1-11 在 Watch1 子窗口中添加了变量“first”。我们还可以直接将变量拖动到 Watch 子窗口的空白 Name 框中。 添加结束后,该变量的值会被显示出来。并且随着单步调试的进行,会看到变量 first 的值逐渐变化。如果各变量的值按照设想的方式逐渐变化,程序运行结果无误,本次开发就顺利结束了。如果发现各变量值的变化和设想的不一致,说明程序存在逻辑错误,那就需要停止调试,返回编辑窗口,查错并修改程序。
3.2.2 程序测试
 在主菜单中选择1
当用户输入1并按回车键后,即可进入数据输入界面。若是第一次运行该程序,应能实现从键盘输入学生信息到结构体struct student中,当输入的学号错误时,应能提示,当输入结束,能结束输入过程,返回主菜单界面。若非第一次运行该程序,应能实现从文件中读入学生信息到结构体struct student中,并进入增加学生记录画面。其输入记录过程如图3.1所示,这里为单条依次输入学生记录。

 在主菜单中选择2
当用户输入2并按回车键后,即可进入浏览学生信息界面。其浏览学生信息记录过程如图3.2所示。

图3.2 浏览学生信息记录
 在主菜单中选择3
当用户输入3并按回车键后,即可进入查询学生信息界面。其查询记录过程如图3.3所示,可按学号进行查询。

图3.3查询学生信息
 在主菜单中选择4
当用户输入4并按回车键后,即可进入记录修改界面。其修改记录过程如图3.4所示,将学号为1851400311的记录的C语言成绩修改成了90分。
图3.4修改学生信息
 在主菜单中选择5
当用户输入5并按回车键后,即可进入删除学生信息界面。可按学号或姓名进行删除。其删除学生信息记录过程如图3.5所示,这里在学号为1851400311的记录删除。

图3.5删除学生信息记录
 在主菜单中选择6
当用户输入6并按回车键后,即可进入排列学生信息界面。可选择数学 、英语 、C语言、总分四种方式进行排序。利用数学成绩排序,其排列结果如图3.6所示。

图3.6排列学生信息
 在主菜单中选择7
当用户输入7并按回车键后,即可进入读取文件界面。其读取文件结果如图3.7所示。

图3.7读取文件

 在主菜单中选择8
当用户输入8并按回车键后,即可进入记录保存界面。其保存结果提示信息如图3.8所示。

图3.8 保存学生记录
 在主菜单中选择9
当用户输入9并按回车键后,即可执行退出管理程序的操作,返回操作系统。其操作结果提示信息如图3.9所示。
图3.9退出管理系统
4、系统维护
经测试与调试确认软件无错时,开发就告一段落,这时可以交付软件供用户使用,但是在软件的使用过程中还会面临更加漫长的工作,即软件维护。一般维护的工作有:更改使用中发现的错误;为适应实际环境而对程序进行修改;为满足新的需求而对程序作必要的改进等等。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值