文档库 最新最全的文档下载
当前位置:文档库 › 学生成绩管理程序

学生成绩管理程序

学生成绩管理程序

一. 功能设计要求

设计要求实现的功能较多,所以将他们分为几个部分叙述。

1.建立文件

(1)可以使用默认文件名或指定文件名将记录存储到文件;

(2)文件保存成功返回0,失败返回-1;

(3)设置保存标志savedtag作为是否已对记录进行存储操作的信息;

(4)写同名文件将覆盖原来文件的内容。

2.增加学生纪录

(1)可在已有记录后面追加新的记录;

(2)可以随时用它增加新的记录,它们仅保存在结构数组中;

(3)可以将一个文件读入,追加在已有记录之后;

(4)如果已经采取用文件追加的方式,在没有保存到文件之前,将继续保持文件追加状态,以便实现连续文件追加操作方式;

(5)如果没有记录存在,给出提示信息。

3.新建学生信息文件

(1)用来重新建立学生信息记录;

(2)如果已经有记录存在,可以覆盖原记录或者在原记录后面追加,也可以将原有记录信息保存到一个指定文件,然后重新建立记录;

(3)给出相应的提示信息。

4.显示记录

(1)如果没有记录可供显示,给出提示信息;

(2)可以随时显示内存中的记录;

(3)显示表头。

5.文件存储

(1)可以按默认名字或指定名字存储记录文件;

(2)存储成功返回0,否则返回-1;

(3)更新存储标志。

6.读取文件

(1)可以按默认名字或指定名字将记录文件读入内存;

(2)读取成功返回0,否则返回-1;

(3)可以将指定或默认文件追加到现有记录的尾部;

(4)可以将文件连续追加到现有记录并更新记录的名次;

(5)更新存储标志。

7.删除记录

(1)可以按“学号”、“姓名”或“名次”方式删除记录;

(2)给出将被删除记录的信息,经确认后再删除;

(3)如果已经是空表,删除时应给出提示信息并返回住菜单;

(4)如果没有要删除的信息,输出没有找到的信息;

(5)应该更新其他记录的名次;

(6)删除操作仅限于内存,只有执行存记录时,才能覆盖原记录;

(7)更新存储标志。

8.修改记录

(1)可以按“学号”、“姓名”或“名次”方式修改记录;

(2)给出将被修改记录的信息,经确认后进行修改;

(3)如果已经是空表,应给出提示信息并返回住菜单;

(4)如果没有找到需要修改的信息,输出提示信息;

(5)应该同时更新其他记录的名次;

(6)修改操作仅限于内存,只有进行存储操作时,才能覆盖原记录;

(7)更新存储标志。

9.查询记录

(1)可以按“学号”、“姓名”或“名次”方式查询记录;

(2)能给出查询记录的信息;

(3)如果查询的信息不存在,输出提示信息。

10.对记录进行排序

(1)可以按学号进行升序或降序排序;

(2)可以按名称进行升序或降序排序;

(3)可以按名次进行升序或降序排序;

(4)如果属于选择错误,可以立即退出排序;

(5)更新存储标志。

11.头文件

(1)使用条件编译定义头文件;

(2)函数原型声明;

(3)数据结构及包含文件。

12.测试程序

(1)应列出测试大纲对程序进行测试;

(2)应保证测试用例测试到程序的各种边缘情况。

以上是基本要求,希望通过对本题设计的理解,重新考虑如何改进设计。

二.总体设计

最初的整体规划只是说明它们的可行性,不要求制定函数的具体实现,甚至不需要考虑函数原型。完成整体规划后,可以按照流程描述各个模块之间的接口功能。

本课程设计对模块设计的要求如下:

(1)要求使用多文件方式实现设计;

(2)要求在各个文件内实现结构化设计

(3)每个模块作为一个单独的C文件,每个文件内的函数如表12-1所示,表中给出了各个函数的功能说明;

(4)宏和数据结构等放在头文件中,并使用条件编译。

本设计有5个C 文件(17个函数)和一个头文件组成,每个C文件都代表着某特定的功能,它们的关系如表12-1所示。本章的设计将更加注意模块化,以便展示C 语言的编程风格。

程序包含文件的存、取过程。它的功能就是按输入顺序建立记录。如果原来没有记录文件,可以重新建立一个文件;如果已经有记录,可以先把文件内容输入,然后把新记录追加到原来记录的尾部;也可以单独建立新文件,以后再使用读取文件的方法拼接。

由上述功能分析可以看到它的全貌。因为它有并列选择,所以可以用选择菜单方便地实现。这个菜单具有10个选择项,用switch语句可以实现这些选择。可以用简洁的伪码对它们进行描述,因为并不复杂,所以不再赘述。

表12-1 文件及函数组成

三.函数设计

为一些函数设计两个返回值一曲分歧执行结果是否正确。每个学生信息资料用一个stuinfo结构来保存,用stuinfo数组全局变量records来保存一批学生的信息资料。

其中的宏定义INITIIAL-SIZE表示数组初始大小,当已经分配的数组大小不够用时,将真假数组的大小,INCR-SIZE为当每次增加的大小。全局变量numstus表示数组中记录的学生数,arraysize视为数组分配的空间大小。全局变量savedtag是信息是否已保存的标志,当属组内容被文件保存值文件后,设为“已保存”状态,当数组内容被修改之后,设为“未保存”状态。

下面分别描述这些函数,建立它们的函数原型。

1.文件存储操作函数

函数原型:int saverecords(void)

功能:将记录存入默认文件stu_info或者指定文件。

参数:void

返回值:成功0,失败-1

工作方式:数组records被保存至指定文件。

要求:报告是否有记录可存、是否能正常建立或打开文件、根据要求执行存

入操作并报告存入记录的条数。

2.文件读取操作函数

函数原型:int loadrecords(void)

功能:将默认文件stu_info或者指定文件里的记录取入内存。

参数:void

返回值:成功0,失败-1

工作方式:records将为从指定文件中读取出的记录。

要求:报告是否有记录可存、能否能正常打开文件、是否覆盖已有记录以及读取记录的条数。

3.显示所有学生信息的函数

函数原型:int display(void)

功能:显示内存里的记录信息

参数:void

返回值:void

工作方式:从头部开始逐个显示记录内容

要求:报告是否有记录及记录条数和内容。

4.增加信息函数

函数原型:void addrecord(void)

功能:增加记录

参数:void

返回值:void

工作方式:从尾部开始逐个追加记录。

要求:将新记录追加在记录尾部,并对记录进行计数。

5.打印表头函数

函数原型:void showtable(void)

功能: 打印表头

参数:void

返回值:void

工作方式:输出一行表头信息

要求:将表头按制表符打印要求。

6.输出在记录中按升序排序的位置

函数原型:void getindex(float sum)

功能: 找出总分为sum在第0至numstus-1个记录中按升序排序的

参数:float,预找出其位置的总分

返回值:int,sum在第0至numstus-1个记录中按升序排序的

工作方式:查找并计数

要求:输出位置整数

7.删除记录函数

函数原型:void removerecord(void)

功能: 删除内存数组中的制定记录

参数:void

返回值:void

工作方式:根据给定的关键字,查找符合的记录并删除。

要求:将后面的记录前移,同时改变名次并给出相关信息。

8.查找指定记录函数

函数原型:void findrecord(char*,int,int)

功能:查找指定的记录。

参数:char*target:预查找记录的某一项与target相同

intb targettype:表明通过哪一项来查找,0为学号,1为姓名,2为名

int form:从第from个记录开始找

返回值:int找到的记录的序号,若找不到则返回-1。

工作方式: 根据给定的关键字,查找符合记录的序号。

要求:找不到则返回-1。

9.查询指定学生信息的函数

函数原型:void queryinfo(void)

功能: 将一个文件的内容追加到另一个文件的尾部。

参数:void

返回值:void

工作方式:可以按照学号、姓名或名次来查询。

要求:打印查询到的学生的信息或给出相关信息。

10.记录复制函数

函数原型:void copyrecord(stuinfo*,stuinfo*)

功能: 将stc指向的一条记录复制给dest指向的记录。

参数:stuinfo*src:源记录stuinfo*dest:目的记录。

返回值:void

工作方式:将源记录逐条复制到目的记录

要求:正确复制字符串。

11.修改指定学生信息函数

函数原型:void modifyrecord(void)

功能: 找到指定记录并修改

参数:void

返回值:void

工作方式: 可以按照学号、姓名或名次找到要修改的记录,确认后方可修改。要求:同时需调整名次

12.学生信息排序函数

函数原型:void sortinfo(void)

功能:对记录进行排序

参数:void

返回值:void

工作方式: 可以按照学号、姓名或名次排序。

要求:升序或降序排序。

13.菜单处理函数

函数原型:void handle_menu(void)

功能:处理选择的菜单命令。

参数:void

返回值:void

工作方式:根据命令,调用相应函数。

要求:给出结束信息。

14.菜单选择函数

函数原型:int menu_select(void)

功能:接受用户选择的命令代码。

参数:void

返回值:int

工作方式:返回命令代码的整数值。

要求:只允许选择规定键,如果输入不合要求,则提醒用户重新输入。

15.新建学生信息记录的函数

函数原型:void newrecords(void)

功能:重新建立输入信息记录。

参数:void

返回值:void

工作方式:根据修要调用saverecords函数。

要求:若原来信息没有保存,则保存原来的信息,然后重新输入信息记录。

16.结束程序运行函数

函数原型:void quit(addr*)

功能: 结束程序运行.

参数:void

返回值:void

工作方式:根据要求决定在推出前是否将修改的记录存入文件。

要求:结束运行之前,询问是否对修改的记录进行存储。

17.主函数

函数原型:void main(void)

功能: 控制程序。

参数:void

返回值:void

要求:管理菜单命令并完成初始化。

18.头部文件

文件名称:student.h

功能:声明函数原型,包含文件及自定义宏和数据结构。

要求:报告是否能正常打开文件执行存入操作及记录的条数。

三.参考程序

1.student.h文件

#ifndef H_STUDENT_HH

#define H_ STUDENT_HH

#include

#include

#include

#include

#define INITIAL_SIZE 100 //树组初始大小

#define INCR_SIZE 50 //数组每次增加的大小

#define NUM_SUBJECT 5 //科目数

struct student_info

{

char number[15]; //学号

char name[20]; //姓名

char gender[4]; //性别

float score[NUM_SUBJECT]; //分别为该学生5门课的成绩

float sum; //总分

float average; //平均分

int index; //名次

};

typedef struct student_info stuinfo;

extern int numstus; //记录的学生数

extern stuinfo*records; //记录学生信息的数组

extern char savetag; //信息是否已保存的标志,0为以保存,1位未保存

extern int arraysize; //数组大小

extern char* subject[];

void handle_menu(void);

int menu_select(void);

void addrecord(void);

void modifyrecord(void)

void display(void);

void queryinfo(void);

void removerecord(void);

void sortinfo(void);

int saverecords(void);

int loadrecords(void);

void newrecords(void);

void quit(void);

void showtable(void);

int findrecord(char*target, int targettype, int from);

int getindex(float sum);

void copyrecord(stuinfo*src, stuinfo*dest);

#endif //H_STUDENT_HH

2.student.c

#include

int numstus=0;

stuinfo *records=null;

char savedtag=0;

int arraysize;

char* subject[]={“语文”,“数学”,“英语”,“物理”,“化学”};

int main()

{

//初始化数组

records=(stuinfo*)malloc(stuinfo)*INITIAL_SIZE);

if (records==null)

{

printf(“memory fail!”);

exit(-1);

}

arraysize = INITIAL_SIZE;

printf(“\n”);

printf(“\t******************************\n”);

printf(“\t* 这是一个*\n”);

printf(“\t* 学生成绩管理程序*\n”);

printf(“\t 可以对学生成绩进行管理*\n”);

printf(“\t 欢迎使用管理程序*\n ”);

printf(“\n”);

handle_menu();

}

void handle_menu(void)

{

for( ; ; )

{

switch(menu_select())

{

case 0:

addrecord();

break;

case 1:

modifyrecord();

break;

case 2:

display();

break;

case 3:

queryinfo();

break;

case 4:

removerecord();

break;

case 5:

sortinfo();

break;

case 6:

saverecords();

break;

case 7:

loadrecords();

break;

case 8:

newrecords();

break;

case 9:

quit();

}

}

}

int menu_select()

{

char s[2];

int cn=0;

printf(“\n”);

printf(“\t0.增加学生信息\n”);

printf(“\t1.修改学生信息\n”);

printf(“\t2.显示学生信息\n”);

printf(“\t3.查询学生信息\n”);

printf(“\t4.删除学生信息\n”);

printf(“\t5.对学生信息进行排序\n”);

printf(“\t6.保存学生信息至记录文件\n”);

printf(“\t7.从记录文件读取学生信息\n”);

printf(“\t8.新建学生信息文件\n”);

printf(“\t9.结束运行\n”);

printf(“\n\t左边数字对应功能选择,请选0-9:”);

for( ; ; )

{

gets(s);

cn=atoi(s);

if(cn==0&&(strcmp(s,”0”)!=0)) cn=11;//处理键入的非数字键,过滤出数字0

if(cn<0||cn>9) printf(“\n\t输出错误,重选0—9:”);

else break;

}

return cn;

}

//新建学生信息记录

void newrecords(void)

{

char str[5];

if(numstus!=0)

{

printf(“现在已经有记录,选择处理已有记录的方法。\n”);

printf(“是否保存原来的记录?(Y/n)”);

gets(str);

if(str[0]!=‘n’&&str[0]!=‘N’)

saverecords();

}

}

numstus=0;

addrecord();

}

//结束运行,退出

void quit(void)

{

char str[5];

if (savedtag==1)

{

printf(“是否保存原来的记录?(Y/n)”);

gets(str);

if(str[0]!=‘n’&&str[0]!=‘N’)

saverecords();

}

free(records);

exit(0);

}

3.add_disp.c

#include

//打印表头

void showtable(void)

{

int j;

printf(“学号\t姓名\t性别”);

for(j=0;j

printf(“\t总分\t平均分\t名次\n”);

}

//显示所有的学生信息

void display(void)

{

int i,j;

if(numstus==0)

{

printf(“没有可供显示记录!”);

return;

}

shoetable();

for (i=0;i

{

//打印学生信息

printf((“%s\t%s\t%s”,records[i].number,records[i].name, records[i].gender);

for(j=0;j

printf(“\t%.1f”,records[i].score[j]);

printf(“\t%.1f\t%.1f\t%d\n”,records[i].sum,records[i].average,records[i].index);

//打印满20个记录后停下来

if (i%20==0&&i!=0)

{

printf(“输入任意字符后继续…\n”);

getch();

printf(“\n\n”);

showtable();

}

}

}

//在当前表的末尾增加新的信息

void addrecord(void)

{

char str[10];

int j;

float mark,sum;

if(numstus==0)

printf(“原来没有记录,现在建立新表\n”);

else

printf(“下面在当前表的末尾增加新的信息\n”);

while(1)

{

printf(“您将要添加一组信息,确定吗?(Y/n)”);

gets(str);

if(str[0]==‘n’||str[0]==‘N’) //不再添加新的信息

break;

if(numstus>=arraysize) //数组空间不足,需要重新申请空间

{

records=realloc(records,(arraysize+INCR_SIZE)*sizeof(stuinfo));

if(records==NULL)

{

printf(“memory failed!”);

exit(-1);

}

arraysize=arraysize+INCR_SIZE;

}

printf(“请输入学号:”);

gets(records[numstus].number);

printf(“请输入姓名:”);

gets(records[numstus].name);

printf(“请输入性别(0为女,1为男):”);

gets(str);

if(str[0]==‘0’)

strcpy(records[numstys].gender,‘女’);

else

strcpy(records[numstys].gender,‘男’);

sum=0;

for(j=0;j

{

printf(“请输入%s成绩:”,subject[j]);

gets(str);

mark=(float)atof(str);

records[numstus].score[j]=mark;

sum+=mark;

}

records[numstus].sum=sum;

records[numstus].average=sum/NUM_SUBJECT;

records[numstus].index=getindex(sum);

numstus++;

}

printf(“现在一共有%d条信息\n”,numstus);

savedtag=1;

}

int i;

int count=0; //总分大于sum的人数

for (i=0;i

{

if (records[i].sum

{

records[i].index++; //总分小于sum的记录名次增1 }

else if (records[i].sum>sum)

{

count++;

}

}

return count+1

}

4.sav_load.c;

#include

int saverecords()

{

FILE *fp;

Char fname[30];

If(numstus==0)

{

printf( “没有记录可存!”);

return –1;

}

printf(“请输入要存入的文件名(直接回车选择文件stus_info):”);

gets(fname);

if(strlen(fname)==0)

strcpy(fname,”stus_info”);

if((fp=fopen(fname,”wb”))==NULL)

{

printf(“不能存入文件!\n”);;

return –1;

}

printf(“\n存文件…\n”);

fwrite(records,sizeof(stuinfo)*numstus,1,fp);

fclose(fp);

printf(“%d条记录已经存入文件,请继续操作。\n”,numstus);

savedtag=0;

return 0; //更新是否已保存的标志}

int loadrecords(void)

{

FILE *fp;

Char fname[30];

Char str[5];

If (numstus!=0&&savedtag==0)

{

printf(“请选择您是要覆盖现有记录(y),还是要将”);

printf(“读取得记录添加到现有记录之后(n)?\n”);

printf(“直接回车则覆盖现有记录\n”);

gets(str);

if(str[0]==‘n’||str[0]==‘N’)

{

savedtag=1;

}

else

{

if ( savedtag==1)

{

printf(“读取文件将会更改原来的记录,”);

printf(“是否保存原来的记录?(Y/n)”);

gets(str);

if (str[0]!==‘n’&&str[0]!==‘N’)

saverecords();

}

numstus=0;

}

}

printf(“请输入要读取得文件名(直接回车选择文件stu_info):”);

gets(fname);

if(strlen(fname)==0)

strcpy(fname,”stu_info”);

if((fp=fopen(fname,”rb”))==NULL)

{

printf(“打不开文件!请重新选择\n”);

return –1;

}

printf(“\n取文件…\n”);

while(!feof(fp))

{

if(numstus>=arraysize)

{

records=realloc(records,(arraysize+INCR_SIZE)*sizeof(stuinfo))

;

if(records==NULL)

{

printf(“memory failed!”);

exit(-1);

}

arraysize= arraysize+INCR_SIZE;

}

if (fread(&records[numstus],

sizeof(stuinfo),1,fp)!=1) break;

records[numstus].index=getindex(records[numstus].sum);numstus++;

}

fclose(fp);

printf(“现在共有%d条记录。”numstus);

return 0;

}

5.quee_remv_modi.c

#include

int findrecord(char*target,int targettype,int from)

{

int i;

for (i=from;i

{

if((targettype==0&&strcmp(target,records[i].number)==0)||

(targettype==1&&strcmp(target,records[i].number)==0)||

(targettype==2&&atoi(target)==records[i].index))

return i;

}

return -1;

}

void queryinfo(void)

{

char str[5];

char target[20];

int type;

int count;

int i,j;

if(numstus==0)

{

printf(“没有可供查询的记录!”);

return;

}

while(1)

{

printf(“请输入查询的方式:(直接输入回车则结束查询)\n”);

printf(“1.按学号\n”);

printf(“2.按姓名\n”);

printf(“3.按名次\n”);

gets(str);

if(strlen(str)==0)

break;

if(str[0]==‘1’)

{

printf(“请输入欲查询的学生的学号:”);

gets(target);

type=0;

}

else if (str[0]==‘2’)

{

printf(“请输入欲查询的学生的姓名:”);

gets(target);

type=1;

}

else

{

printf(“请输入欲查询的学生的名次:”);

gets(target);

type=2;

}

i=findrecord(target,type,o);

if(i==1)

{

showtable();

}

count =0;

while(i!=-1)

{

count++;

printf((“%s\t%s\t%s”,records[i].number,records[i].name, records[i].gender);

for(j=0;j

printf(“\t%.1f”,records[i].score[j]);

printf(“\t%.1f\t%.1f\t%d\n”,records[i].sum,records[i].average,records[i].index);

I=findrecord(target,type,i+1);

}

if (count==0)

printf(“没有符合条件的学生!\n”);

else

printf(“一共找到了%d名学生的信息\n\n”,count);

}

}

void removerecord(void)

{

char str[5];

char target[20];

int type;

int tmpi;

int i,j;

if(numstus==0)

{

printf(“没有可供删除的记录!”);

return;

}

while(1)

{

printf(“请输入如何找到欲删除的记录的方式:”);

printf(“(直接输入回车则结束移除操作)\n”);

printf(“1.按学号\n”);

printf(“2.按姓名\n”);

printf(“3.按名次\n”);

gets(str);

if(strlen(str)==0)

break;

if(str[0]==‘1’)

{

printf(“请输入欲查询的学生的学号:”);

gets(target);

type=0;

}

else if (str[0]==‘2’)

{

printf(“请输入欲查询的学生的姓名:”);

gets(target);

type=1;

}

else

{

printf(“请输入欲查询的学生的名次:”);

gets(target);

type=2;

}

i=findrecord(target,type,o);

if(i==-1) printf(“没有符合条件的学生!\n”);

while(i!=-1)

{

showtable();

printf((“%s\t%s\t%s”,records[i].number,records[i].name, records[i].gender);

for(j=0;j

printf(“\t%.1f”,records[i].score[j]);

printf(“\t%.1f\t%.1f\t%d\n”,records[i].sum,records[i].average,records[i].index);

printf(“确定要删除这个学生的的信息吗?(Y/N)”);

gets(str);

}

if(str[0]==‘y’||STR[0]==‘Y’)

{

numstus--;

tmpi=records[i].index;

for(j=i;j

{

copyrecord(&records[j+1],&records[j]);

}

for(j=0; j

{

if(records[j].index>tmpi)

records[j].index--;

}

i=findrecord(target,type,i++);

}

}

savedtag=1;

}

void copyrecord(stuinfo*src,stuinfo*dest)

{

int j;

strcpy(dest->number,src->number);

strcpy(dest->name,src->name);

strcpy(dest->gender,src->gender);

for(j=0;j

{

dest->score[j]=src->score[j];

}

dest->sum=src->sum;

dest->average=src->average;

dest->index=src->index;

void modifyrecord(void)

{

char str[5];

char target[20];

int type;

int tmpi;

float sum,mark;

int count=0;

if(numstus==0)

{

printf(“没有可供选择的记录!”);

return;

}

while(1)

{

printf(“请输入如何找到欲修改的记录的方式:”);

printf(“(直接输入回车则结束移除操作)\n”);

printf(“1.按学号\n”);

printf(“2.按姓名\n”);

printf(“3.按名次\n”);

gets(str);

if(strlen(str)==0)

break;

if(str[0]==‘1’)

{

printf(“请输入欲查询的学生的学号:”);

gets(target);

type=0;

}

else if (str[0]==‘2’)

{

printf(“请输入欲查询的学生的姓名:”);

gets(target);

type=1;

}

else

{

printf(“请输入欲查询的学生的名次:”);

gets(target);

type=2;

}

i=findrecord(target,type,o);

if(i==-1) printf(“没有符合条件的学生!\n”);

while(i!=-1)

{

showtable();

printf((“%s\t%s\t%s”,records[i].number,records[i].name, records[i].gender);

for(j=0;j

printf(“\t%.1f”,records[i].score[j]);

printf(“\t%.1f\t%.1f\t%d\n”,records[i].sum,records[i].average,records[i].index);

printf(“确定要修改这个学生的的信息吗?(Y/N)”);

gets(str)

if(str[0]==‘y’||STR[0]==‘Y’)

{

tmpi=records[i].index;

printf(“下面请重新输入该学生的信息:\n”);

printf(“请输入学号:”);

gets(records[numstus].number);

printf(“请输入姓名:”);

gets(records[numstus].name);

printf(“请输入性别(0为女,1为男):”);

gets(str);

if(str[0]==‘0’)

strcpy(records[numstys].gender,‘女’);

else

strcpy(records[numstys].gender,‘男’);

sum=0;

for(j=0;j

{

printf(“请输入%s成绩:”,subject[j]);

gets(str);

mark=(float)atof(str);

records[i].score[i]=mark;

sum+=mark;

}

records[i].sum=sum;

records[i].average=sum/NUM_SUBJECT;

count=0;

for(j=0;j

{

if(j==I)continue;

if(records[j].index>tmpi&&records[j].sum>sum)

records[j].index--;

elseif(records[j].index<=tmpi&&records[j].sum

records[j].index++;

if(records[j].sum>sum)

count++;

}

records[j].index=count+1;

}

i=findrecord(target,type,i++);

}

}

savedtag=1;

}

6.sort.h

#include

相关文档
相关文档 最新文档