C语言实现学生成绩管理系统实战教学
趁着放假无事,开始用C语言开发一些小的项目,巩固基础知识的同时学习新的知识。
学生成绩管理系统实现的功能有:成绩录入、学生成绩查询、删除、修改、通过文件保存等。
开发这样一个系统需要具备的知识:线性表(链表)、文件操作、排序(如果需要成绩排序)。
开发环境为VS2015;在Linux下没有conio.h的头文件,需要修改与getch()函数相关的代码。
#include#include #include #include /*学生信息结构体*/ typedefstructNode { charName[10]; //学生姓名 charID[15]; //学生学号 intScore[3]; //三科成绩(数学、英语、数据结构) floatAve_Sco; structNode*next; }Lnode; voidDisplay();/*界面显示函数*/ voidGetScore(Lnode*&h);/*成绩录入函数*/ voidPrintScore(Lnode*h);/*成绩打印函数*/ voidModifyScore(Lnode*h);/*成绩修改函数*/ voidFindInf(Lnode*h);/*查找信息*/ voidDelete(Lnode*h);/*删除函数*/ voidQuit(Lnode*h);/*退出函数*/ voidSaveInf(Lnode*h); voidLoadInf(Lnode*h); /*初始化链表*/ voidInitList(Lnode*&head) { head=(Lnode*)malloc(sizeof(Lnode)); if(head==NULL) { printf("error!"); exit(1); } head->next=NULL;//使头节点指针域为空 } intmain() { Lnode*ScoreList;//建立成绩链表,所有学生信息存放在此链表 intFunction; charflag; intt=0; InitList(ScoreList); LoadInf(ScoreList); while(1) { Display(); printf("请选择操作:"); scanf("%d",&Function); switch(Function) { case1:while(1) { GetScore(ScoreList); printf("是否继续输入(Y/N)"); scanf("%s",&flag); if(flag=='N'||flag=='n')break; } system("cls");break; case2:PrintScore(ScoreList); _getch();system("cls");break; case3:ModifyScore(ScoreList); system("cls");break; case4:FindInf(ScoreList);_getch();system("cls");break; case5:Delete(ScoreList);_getch();system("cls");break; case6:Quit(ScoreList);break; default:printf("Error!!!请重新输入:"); break; }//switch结束 } return0; } /*系统界面显示*/ voidDisplay() { printf("\t\t**********************************************\n"); printf("\t\t*************欢迎使用成绩管理系统*************\n"); printf("\t\t**********************************************\n"); printf("\t\t\t\t1、录入成绩\n"); printf("\t\t\t\t2、打印成绩\n"); printf("\t\t\t\t3、修改成绩\n"); printf("\t\t\t\t4、查找学生信息\n"); printf("\t\t\t\t5、删除学生信息\n"); printf("\t\t\t\t6、退出系统\n"); printf("\n\n\n\n\n\n"); } /*成绩录入*/ voidGetScore(Lnode*&h) { Lnode*p,*q=h; charname[10],id[15]; intMath,English,Datastruct; p=(Lnode*)malloc(sizeof(Lnode)); //为学生信息申请节点 printf("请依次输入学生信息:\n"); printf("姓名学号数学英语数据结构\n"); scanf("%s%s%d%d%d",&name,&id,&Math,&English,&Datastruct); for(;q->next!=NULL;q=q->next){;}//移动到尾节点 strcpy(p->Name,name); strcpy(p->ID,id); p->Score[0]=Math; p->Score[1]=English; p->Score[2]=Datastruct; p->Ave_Sco=((float)((p->Score[0]+p->Score[1]+p->Score[2])-150))/30; p->next=NULL; q->next=p; q=p; } /*成绩打印*/ voidPrintScore(Lnode*h) { Lnode*p=h->next; printf("%-14s%-8s%-8s%-8s%-8s%-8s\n","排名","学号","姓名","数学","英语","数据结构","平均绩点"); while(p!=NULL) { printf("%-14s%-8s%-8d%-8d%-8d%.2f\n",p->ID,p->Name,p->Score[0],p->Score[1],p->Score[2],p->Ave_Sco); p=p->next; } } /*成绩修改*/ voidModifyScore(Lnode*h) { Lnode*p=h->next; charname[10],id[15]; intMath,English,Datastruct; printf("请输入学生姓名:"); scanf("%s",name); printf("请输入学生学号:"); scanf("%s",id); while(p) { if(strcmp(p->Name,name)==0&&strcmp(p->ID,id)==0) { printf("当前学生信息:\n"); printf("%-14s%-8s%-8s%-8s%-8s\n","学号","姓名","数学","英语","数据结构"); printf("%-14s%-8s%-8d%-8d%-8d\n",p->ID,p->Name,p->Score[0],p->Score[1],p->Score[2]); printf("请输入更正后的数学成绩:"); scanf("%d",&Math); printf("请输入更正后的英语成绩:"); scanf("%d",&English); printf("请输入更正后的数据结构成绩:"); scanf("%d",&Datastruct); p->Score[0]=Math; p->Score[1]=English; p->Score[2]=Datastruct; break; } else { p=p->next; } }//while循环结束 } /*信息查找*/ voidFindInf(Lnode*h) { Lnode*p=h->next; charname[10],id[15]; printf("请输入学生姓名:"); scanf("%s",name); printf("请输入学生学号:"); scanf("%s",id); while(p) { if(strcmp(p->Name,name)==0&&strcmp(p->ID,id)==0) { printf("当前学生信息:\n"); printf("%-14s%-8s%-8s%-8s%-8s\n","学号","姓名","数学","英语","数据结构"); printf("%-14s%-8s%-8d%-8d%-8d\n",p->ID,p->Name,p->Score[0],p->Score[1],p->Score[2]); break; } else { p=p->next; } }//while循环结束 } /*删除*/ voidDelete(Lnode*h) { Lnode*p=h,*q; q=p->next; charname[10],id[15]; printf("请输入学生姓名:"); scanf("%s",name); printf("请输入学生学号:"); scanf("%s",id); while(q) { if(strcmp(q->Name,name)==0&&strcmp(q->ID,id)==0) { p->next=q->next; free(q);//删除p节点 printf("删除成功\n"); break; } else { p=p->next; q=q->next; } }//while循环结束 } /*退出系统*/ voidQuit(Lnode*h) { SaveInf(h);//退出时保存信息 exit(0); } /*打开文件*/ voidLoadInf(Lnode*h) { Lnode*p=h; Lnode*q;//临时变量用于保存从文件中读取的信息 FILE*file=fopen("./Information.dat","rb"); if(!file) { printf("文件打开失败!"); return; } /* 使用feof判断文件是否为结束要注意的问题: 当读取文件结束时,feof函数不会立即设置标志符为-1,而是 需要再读取一次后,才会设置。所以要先读一次。 */ q=(Lnode*)malloc(sizeof(Lnode)); fread(q,sizeof(Lnode),1,file); while(!feof(file))//一直读到文件末尾 { p->next=q; p=q; q=(Lnode*)malloc(sizeof(Lnode)); fread(q,sizeof(Lnode),1,file); }//while循环结束 p->next=NULL; fclose(file); } /*保存信息到文件中*/ voidSaveInf(Lnode*h) { Lnode*p=h->next; intflag; FILE*file=fopen("./Information.dat","wb"); if(!file) { printf("文件打开失败!"); return; } while(p!=NULL) { flag=fwrite(p,sizeof(Lnode),1,file);//将p的内容写到文件中 if(flag!=1) { break; } p=p->next; } fclose(file); }
虽然是很简单的小项目,还是有很多问题。
一:链表相关
在写成绩录入和成绩打印功能时,发现始终只能保存(没加入文件保存)最后一个数据,确定链表的相关操作没有问题,仔细判断逻辑关系后,发现是每次在头节点传到GetScore()函数,为新节点申请内存后,直接将数据保存在了新申请的节点里面,没有将链表移动到尾节点,导致每次录入成绩,都会覆盖前一次输入的数据。解决办法是链表传到函数后,先移动到最后一个节点,将新申请的节点挂接在最后一个节点之后。
/*成绩录入*/ voidGetScore(Lnode*&h) { Lnode*p,*q=h; charname[10],id[15]; intMath,English,Datastruct; p=(Lnode*)malloc(sizeof(Lnode)); //为学生信息申请节点 printf("请依次输入学生信息:\n"); printf("姓名学号数学英语数据结构\n"); scanf("%s%s%d%d%d",&name,&id,&Math,&English,&Datastruct); for(;q->next!=NULL;q=q->next){;}//移动到尾节点 //保存数据 strcpy(p->Name,name); strcpy(p->ID,id); p->Score[0]=Math; p->Score[1]=English; p->Score[2]=Datastruct; p->Ave_Sco=((float)((p->Score[0]+p->Score[1]+p->Score[2])-150))/30; //始终指向最后一个节点 p->next=NULL; q->next=p; q=p; }
二、文件操作
用文件保存遇到的问题主要是每次打印数据时除正常数据外,始终多一行乱码。判断方法是while(!feof(file))。排除错误时确定了两种可能性:多保存了一行;多读取了一行。经过某度feof()与EOF的关系后,确定是多读取了一行数据。
用feof()函数进行文件尾判断时,当文件已经到达尾部后,还需要在读取一次后,feof()函数才会返回-1,所以会出现多读一次的情况;解决办法时,在循环读取之前先将第一个数据读取出来,然后在正常读取。即注意多读一次的问题。
/*打开文件*/ voidLoadInf(Lnode*h) { Lnode*p=h; Lnode*q;//临时变量用于保存从文件中读取的信息 FILE*file=fopen("./Information.dat","rb"); if(!file) { printf("文件打开失败!"); return; } /* 使用feof判断文件是否为结束要注意的问题: 当读取文件结束时,feof函数不会立即设置标志符为-1,而是 需要再读取一次后,才会设置。所以要先读一次。 */ q=(Lnode*)malloc(sizeof(Lnode)); fread(q,sizeof(Lnode),1,file); while(!feof(file))//一直读到文件末尾 { p->next=q; p=q; q=(Lnode*)malloc(sizeof(Lnode)); fread(q,sizeof(Lnode),1,file); }//while循环结束 p->next=NULL; fclose(file); }