学生成绩管理程序 | ||||||||||||||||
一. 功能设计要求 设计要求实现的功能较多,所以将他们分为几个部分叙述。 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语句可以实现这些选择。可以用简洁的伪码对它们进行描述,因为并不复杂,所以不再赘述。 三.函数设计 为一些函数设计两个返回值一曲分歧执行结果是否正确。每个学生信息资料用一个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(“”); printf(“******************************”); printf(“* 这是一个*”); printf(“* 学生成绩管理程序*”); printf(“可以对学生成绩进行管理*”); printf(“欢迎使用管理程序*”); printf(“”); 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(“”); printf(“.增加学生信息”); printf(“.修改学生信息”); printf(“.显示学生信息”); printf(“.查询学生信息”); printf(“.删除学生信息”); printf(“.对学生信息进行排序”); printf(“.保存学生信息至记录文件”); printf(“.从记录文件读取学生信息”); printf(“.新建学生信息文件”); printf(“.结束运行”); printf(“左边数字对应功能选择,请选0-9:”); for( ; ; ) gets(s); cn=atoi(s); if(cn==0&&(strcmp(s,”0”)!=0)) cn=11;//处理键入的非数字键,过滤出数字0 if(cn9) printf(“输出错误,重选0—9:”); else break; return cn; //新建学生信息记录 void newrecords(void) char str[5]; if(numstus!=0) printf(“现在已经有记录,选择处理已有记录的方法。”); 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) gets(str); saverecords(); :free(records); exit(0); 3.add_disp.c #include void showtable(void) int j; for(j=0;j void display(void) int i,j; if(numstus==0) return; shoetable(); for (i=0;i printf((¡°%s%s%s¡±,records[i].number,records[i].name, records[i].gender); for(j=0;j printf(¡°%.1f¡±,records[i].score[j]); printf(¡°%.1f%.1f%d¡±,records[i].sum,records[i].average,records[i].index); if (i ==0&&i!=0) printf(¡°ÊäÈëÈÎÒâ×Ö•ûºó¼ÌÐø¡¡±); getch(); printf(¡°¡±); showtable(); void addrecord(void) char str[10]; int j; float mark,sum; if(numstus==0) else while(1) gets(str); break£» if(records==NULL) printf(¡°memory failed!¡±); exit(-1); arraysize=arraysize INCR_SIZE; gets(records[numstus].number); gets(records[numstus].name); gets(str); if(str[0]==¡®0¡¯) sum=0; for(j=0;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 ; savedtag=1; int i; for (i=0;i if (records[i].sum else if (records[i].sum>sum) count ; return count 1
|