使用C语言实现学生成绩管理系统
程序员文章站
2022-03-12 20:17:40
最近正在学习c语言,搞了一个学生成绩管理系统的小程序,代码粗陋,大佬勿喷。先上图:整个程序采用链表来管理学生成绩,保存学生成绩用的是 文件处理函数,使用 fopen(filepath, “wb”) 将...
最近正在学习c语言,搞了一个学生成绩管理系统的小程序,代码粗陋,大佬勿喷。
先上图:
整个程序采用链表来管理学生成绩,保存学生成绩用的是 文件处理函数,使用 fopen(filepath, “wb”) 将学生信息在内存中的数据直接写入文件,相应的打开程序后读取时使用 fopen(filepath, “rb”) 将数据直接再次还原到内存中去。
选项6 是手动保存链表数据及配置数据。
选项7 配置每次修改链表中的数据是否需要自动保存。
选项1 进入后,直接按照提示输入 学生的各个信息,一行一个
选项3 修改学生信息,进入后选择以什么方式查找要修改的学生,然后输入学生的学号或姓名,找到之后(因为可能存在重名的同学,所以这里做了序号索引),输入结果索引,然后根据提示将该学生的信息重新输入一遍,达到修改的效果。
选项4 查询,功能如上图所示
选项5 排序,根据提示输入条件,排序会导致链表数据改变,所以回到主菜单后会自动保存数据到文件
选项8 投票系统,输入链表中存在的人名,对应下方投票结果会实时变动,并排序,最高票数的人颜色高亮。
选项9 输入后右侧出现提示“导出成功”,则在相应目录下会出现student_export.txt文件,里面包含有链表中所有学生信息,这里采用的是 fprintf 函数输出到文件。
链表排序时,数据交换使用了kernel32.dll 中的内存数据拷贝 movememory 函数,只需要将除链表中的pnext 以外的数据进行拷贝交换即可。
下面上代码:
// 学生管理系统.cpp : defines the entry point for the console application. // #include "stdafx.h" #include "string.h" #include "conio.h" #include "windows.h" #include "stdlib.h" #define list_title "学号 姓名 性别 语文 数学 英语\n" #define list_title_1 "学号 姓名 性别 语文 数学 英语 均分\n" #define file_database "c:\\student_database.dat" #define file_export "c:\\student_export.txt" //颜色 enum { black, blue, green, cyan, red, magenta, brown, lightgray, darkgray, lightblue, lightgreen, lightcyan, lightred, lightmagenta, yellow, white }; //功能索引 enum { func_add = 1,//添加学生信息 func_delete,//删除 func_modify,//修改 func_search,//搜索 func_sort,//排序 func_save,//保存 func_autosave,//自动保存 func_vote,//投票系统 func_export,//导出学生信息 func_exitsystem//退出系统 }; struct student { int num;//学号 char name[20];//姓名 char sex[8];//性别 float score[3];//三门课程成绩 float averge;//平均分 int count;//投票计数 student* pnext; }; student* g_pstuhead;//链表头 bool g_autostore = false;//自动保存 /************************************************************************/ /*设置字体颜色*/ /************************************************************************/ void setfontcolor(int forgc) { word wcolor; handle houtput = getstdhandle(std_output_handle); console_screen_buffer_info csbi; if(getconsolescreenbufferinfo(houtput, &csbi)) { //设置字体颜色 wcolor = (csbi.wattributes & 0xf0) + (forgc & 0x0f); setconsoletextattribute(houtput, wcolor); } } /************************************************************************/ /*光标跳转到指定位置*/ /************************************************************************/ void gotoxy(int x, int y) { // 更新光标位置 coord pos; handle houtput = getstdhandle(std_output_handle); pos.x = x; pos.y = y; setconsolecursorposition(houtput, pos); // 隐藏光标 // console_cursor_info cursor; // cursor.bvisible = false; // cursor.dwsize = 1; //值介于1 ~ 100 之间 单元格底部为下划线 ~ 完全填充单元格 // setconsolecursorinfo(houtput, &cursor); } /************************************************************************/ /*主菜单中指定位置打印是否自动保存*/ /************************************************************************/ void printautostoreinfo() { setfontcolor(lightgreen); gotoxy(13, 10); printf("%s\n", g_autostore ? "是" : "否"); setfontcolor(white); } /************************************************************************/ /*显示最上面的系统标题*/ /************************************************************************/ void showsystemtitle() { setfontcolor(lightgreen); printf("--------------------------------------------------------\n"); printf("\t\t欢迎进入学生管理系统\n"); printf("--------------------------------------------------------\n"); setfontcolor(white); } /************************************************************************/ /*初始化屏幕*/ /************************************************************************/ void initscreen() { system("cls"); showsystemtitle(); printf("请输入数字序列号,选择您要执行的操作:\n"); printf("1、添加学生信息\n"); printf("2、删除学生信息\n"); printf("3、修改学生信息\n"); printf("4、查询学生信息\n"); printf("5、排序\n"); printf("6、保存(如打开自动保存,则无需手动执行)\n"); printf("7、自动保存:"); printautostoreinfo(); printf("8、投票系统\n"); printf("9、导出学生信息\n"); setfontcolor(lightred); printf("10、退出学生管理系统\n"); setfontcolor(white); } /************************************************************************/ /*从指定位置开始清除指定长度元素*/ /************************************************************************/ void gotodelete(int x, int y, int length) { int i; for (i = 0; i < length; i++) { gotoxy(x + i, y); printf(" "); } } /************************************************************************/ /*清除指定位置元素*/ /************************************************************************/ void gotodelete(int x, int y) { gotodelete(x, y, 1); } /************************************************************************/ /*投票系统 */ /************************************************************************/ void votesystem() { bool hasfound; char name[20]; int count, i, j; student* pstu, *ptmp; student** pstuarr; //初始化票数清零 pstu = g_pstuhead->pnext; while(pstu != null) { pstu->count = 0; pstu = pstu->pnext; } count = 0; pstuarr = (student**)malloc(4 * 100);//用于存放已经获得票数的同学指针 gotoxy(0, 6); printf("投票结果如下:\n"); gotoxy(0, 3); printf("请在下方输入你想投给的人的姓名(输入-1返回主菜单):\n"); while (1) { gotodelete(0, 4, 20);//清空输入行 gotoxy(0, 4); scanf("%s", name); if(strcmp(name, "-1") == 0) { break; } hasfound = false; pstu = g_pstuhead->pnext; //在系统中查找对应的人名 while(pstu != null) { if(strcmp(pstu->name, name) == 0) { hasfound = true; break; } pstu = pstu->pnext; } if(! hasfound) { printf("查无此人!!!"); sleep(1000); gotodelete(0, 5, 20); continue; } //找到之后,这个人所对应的票数+1 pstu->count++; for (i = 0; i < count; i++) { if(pstuarr[i] == pstu) { break; } } if(i == count)//说明未找到,则添加进候选人数组 { pstuarr[count++] = pstu; if(count % 100 == 0) { pstuarr = (student**)realloc(pstuarr, count + 100); } } //冒泡排序,票数 for (i = 0; i < count - 1; i++) { for (j = i + 1; j < count; j++) { if(pstuarr[i]->count < pstuarr[j]->count) { ptmp = pstuarr[i]; pstuarr[i] = pstuarr[j]; pstuarr[j] = ptmp; } } } gotoxy(0, 7);//跳转到打印票数的那行 //打印票数 for (i = 0; i < count; i++) { if(i == 0) { setfontcolor(lightgreen); } else { setfontcolor(white); } printf("%d %s\t%d\n", pstuarr[i]->num, pstuarr[i]->name, pstuarr[i]->count); } } free(pstuarr); } /************************************************************************/ /*导出学生信息(明文) */ /************************************************************************/ bool exportstudentinfo() { student* pstu; file* fp; pstu = g_pstuhead->pnext; if((fp = fopen(file_export, "w")) == null) { return false; } while (pstu != null) { fprintf(fp, "%d %s %s %.2f %.2f %.2f %.2f\n", pstu->num, pstu->name, pstu->sex, pstu->score[0], pstu->score[1], pstu->score[2], pstu->averge); pstu = pstu->pnext; } fclose(fp); return true; } /************************************************************************/ /*保存学生信息 (以数据库形式保存)*/ /************************************************************************/ bool savestudentinfo() { file *fp; student *pstu; pstu = g_pstuhead; if((fp = fopen(file_database, "wb")) == null) { return false; } fwrite(&g_autostore, sizeof(g_autostore), 1, fp); while (pstu != null) { fwrite(pstu, sizeof(student), 1, fp); pstu = pstu->pnext; } fclose(fp); return true; } /************************************************************************/ /*读取学生信息(读取数据库形式的文档) */ /************************************************************************/ bool loadstudentinfo() { file *fp; int count; student stu, *pstu, *pstunew; count = 0; pstu = g_pstuhead; if((fp = fopen(file_database, "rb")) == null) { return false; } fread(&g_autostore, sizeof(g_autostore), 1, fp);//读取是否自动保存 while(1) { fread(&stu, sizeof(student), 1, fp);//读取文档中每个同学的数据 if(feof(fp))//到文档尾则跳出 { break; } if(count++ > 0)//这里 > 0 是因为保存的时候会把链表头保存进去,而链表头是没有有效数据的,所以要排除掉 { pstunew = (student*)malloc(sizeof(student)); movememory(pstunew, &stu, sizeof(student) - 4);//将结构体除指针外的所有数据拷贝进内存 pstunew->pnext = null; pstu->pnext = pstunew; pstu = pstunew; } if(stu.pnext == null) { break; } } fclose(fp); return true; } /************************************************************************/ /*学生信息排序 */ /************************************************************************/ bool sortstudentinfo() { int order1, order2; bool swapdata; char yesorno; student* pstu1, *pstu2, tmpstu; pstu1 = g_pstuhead->pnext; if(pstu1 == null) { printf("系统中无学生信息!\n"); system("pause"); return false; } printf("输入以下序号执行相应功能(输入其他序号返回主菜单):\n"); printf("1、根据学号进行排序\n"); printf("2、根据姓名排序\n"); printf("3、根据语文成绩排序\n"); printf("4、根据数学成绩排序\n"); printf("5、根据英语成绩排序\n"); printf("6、根据平均分成绩排序\n"); scanf("%d", &order1); if(order1 >= 1 && order1 <= 6) { printf("请选择正序or倒序排列?(输入其他序号返回主菜单)\n"); printf("1、正序排列\n"); printf("2、倒序排列\n"); scanf("%d", &order2); if(order2 >= 1 && order2 <= 2) { //冒泡排序 for ( ; pstu1->pnext != null; pstu1 = pstu1->pnext) { for (pstu2 = pstu1->pnext; pstu2 != null; pstu2 = pstu2->pnext) { swapdata = false;//是否交换数据 switch(order1) { case 1://根据学号排序 { if(order2 == 1 ? (pstu1->num > pstu2->num) : (pstu1->num < pstu2->num))//三目运算符, 判断正序还是倒序 { swapdata = true; } break; } case 2://根据姓名排序 { if(order2 == 1 ? (strcmp(pstu1->name, pstu2->name) > 0) : (strcmp(pstu1->name, pstu2->name) < 0)) { swapdata = true; } break; } case 3://根据语文排序 case 4://根据数学排序 case 5://根据英语排序 { if(order2 == 1 ? (pstu1->score[order1 - 3] > pstu2->score[order1 - 3]) : (pstu1->score[order1 - 3] < pstu2->score[order1 - 3])) { swapdata = true; } break; } case 6://根据均分排序 { if(order2 == 1 ? (pstu1->averge > pstu2->averge) : (pstu1->averge < pstu2->averge)) { swapdata = true; } break; } } if(swapdata) { //交换内存数据,只需要将除pnext指针外的结构体数据拷贝交换即可 movememory(&tmpstu, pstu1, sizeof(student) - 4); movememory(pstu1, pstu2, sizeof(student) - 4); movememory(pstu2, &tmpstu, sizeof(student) - 4); } } } printf("排序完成,是否显示?y/n\n"); getchar();//过滤掉输入时的换行符 scanf("%c", &yesorno); if(yesorno == 'y' || yesorno == 'y') { pstu1 = g_pstuhead->pnext; setfontcolor(lightgreen); printf(list_title_1);//显示列表标题头 setfontcolor(white); //打印排序后的各个学生信息 while(pstu1 != null) { printf("%d %s %s %.2f %.2f %.2f %.2f\n", pstu1->num, pstu1->name, pstu1->sex, pstu1->score[0], pstu1->score[1], pstu1->score[2], pstu1->averge); pstu1 = pstu1->pnext; } system("pause"); } return true; } } return false; } /************************************************************************/ /*查询学生信息 */ /************************************************************************/ void searchstudentinfo() { bool hasfound; int order, stuid, count, i, min, max; float score; char name[20]; student* pstu; student** pstuarr; pstuarr = null; while (1) { system("cls"); showsystemtitle(); if(pstuarr != null)//如果再次查询,这里需要判断,将上一轮查询的学生信息指针数组清空 { free(pstuarr); } count = 0; stuid = 0; hasfound = false; pstu = g_pstuhead->pnext; pstuarr = (student**)malloc(4 * 100);//初始化查询到后存放的学生信息指针数组 printf("输入以下序号执行相应功能(输入其他序号返回主菜单):\n"); printf("1、输入学号查询信息\n"); printf("2、输入姓名查询信息\n"); printf("3、输入语文成绩范围查询信息\n"); printf("4、输入数学成绩范围查询信息\n"); printf("5、输入英语成绩范围查询信息\n"); printf("6、输入平均分范围查询信息\n"); printf("7、列出所有学生信息\n"); scanf("%d", &order); switch(order) { case 1://根据学号查询 { printf("请输入要查询的学生学号:"); scanf("%d", &stuid); while (pstu != null) { if(pstu->num == stuid) { hasfound = true; break; } pstu = pstu->pnext; } if(hasfound)// { setfontcolor(lightgreen); printf(list_title_1); setfontcolor(white); printf("%d %s %s %.2f %.2f %.2f %.2f\n", pstu->num, pstu->name, pstu->sex, pstu->score[0], pstu->score[1], pstu->score[2], pstu->averge); } break; } case 2://根据姓名查询 { printf("请输入要查询的学生姓名:"); scanf("%s", name); while (pstu != null) { if(strcmp(pstu->name, name) == 0) { hasfound = true; pstuarr[count++] = pstu; if(count % 100 == 0) { pstuarr = (student**)realloc(pstuarr, count + 100); } } pstu = pstu->pnext; } if(hasfound) { setfontcolor(lightgreen); printf(list_title_1); setfontcolor(white); for (i = 0; i < count; i++) { printf("%d %s %s %.2f %.2f %.2f %.2f\n", pstuarr[i]->num, pstuarr[i]->name, pstuarr[i]->sex, pstuarr[i]->score[0], pstuarr[i]->score[1], pstuarr[i]->score[2], pstuarr[i]->averge); } } break; } case 3://根据语文成绩范围查询 case 4://根据数学成绩范围查询 case 5://根据英语成绩范围查询 case 6://根据平均分范围查询 { char *subjectstrarr[4] = {"语文", "数学", "英语", "平均"}; printf("请输入要查询的%s成绩范围:", subjectstrarr[order - 3]); scanf("%d %d", &min, &max); while (pstu != null) { if(order < 6)// 3 ~ 5 { score = pstu->score[order - 3]; } else //order = 6 { score = pstu->averge; } if(score >= min && score <= max) { //找到符合条件的学生信息,则加入到指针数组中去 hasfound = true; pstuarr[count++] = pstu; if(count % 100 == 0) { pstuarr = (student**)realloc(pstuarr, count + 100); } } pstu = pstu->pnext; } if(hasfound) { setfontcolor(lightgreen); printf(list_title_1); setfontcolor(white); //打印指针数组中的学生信息 for (i = 0; i < count; i++) { printf("%d %s %s %.2f %.2f %.2f %.2f\n", pstuarr[i]->num, pstuarr[i]->name, pstuarr[i]->sex, pstuarr[i]->score[0], pstuarr[i]->score[1], pstuarr[i]->score[2], pstuarr[i]->averge); } } break; } case 7://列出所有学生信息 { hasfound = true; setfontcolor(lightgreen); printf(list_title_1); setfontcolor(white); while(pstu != null) { printf("%d %s %s %.2f %.2f %.2f %.2f\n", pstu->num, pstu->name, pstu->sex, pstu->score[0], pstu->score[1], pstu->score[2], pstu->averge); pstu = pstu->pnext; } break; } default: { goto lab_search; } } if(! hasfound) { printf("未能找到相应的学生信息!\n"); } system("pause"); } lab_search: free(pstuarr); } /************************************************************************/ /*删除学生信息 */ /************************************************************************/ bool deletestudentinfo() { char yesorno; int stuid; bool hasfound; student* pstu, *pstu1; hasfound = false; pstu = g_pstuhead->pnext; pstu1 = g_pstuhead; printf("请输入欲删除的学生学号:"); scanf("%d", &stuid); while (pstu != null) { if(pstu->num == stuid) { hasfound = true; break; } pstu1 = pstu; pstu = pstu->pnext; } if(hasfound) { printf("找到此学生的信息如下:\n"); setfontcolor(lightgreen); printf(list_title_1); setfontcolor(white); printf("%d %s %s %.2f %.2f %.2f %.2f\n", pstu->num, pstu->name, pstu->sex, pstu->score[0], pstu->score[1], pstu->score[2], pstu->averge); printf("是否删除?y/n"); getchar();//过滤掉输入时的换行符 scanf("%c", &yesorno); if(yesorno == 'y' || yesorno == 'y') { pstu1->pnext = pstu->pnext; free(pstu); printf("已删除\n"); } else { hasfound = false; } } else { printf("未找到对应学生的信息\n"); } system("pause"); return hasfound; } /************************************************************************/ /*修改学生信息 */ /************************************************************************/ bool modifystudentinfo() { int order, count, i; int stuid; char name[20]; char yesorno; bool hasmodify; student* pstu; student** pstuarr; hasmodify = false; count = 0; pstu = g_pstuhead->pnext; pstuarr = (student**)malloc(4 * 100);//用于存放查找到的学生信息指针,这里定义指针数组是防止查询姓名出现重名 printf("请输入以下序号,选择对应功能(1或2,否则返回上级菜单)\n"); printf("1、输入学号查找学生\n"); printf("2、输入姓名查找学生\n"); scanf("%d", &order); if(order == 1) { printf("请输入要修改的学生学号:\n"); scanf("%d", &stuid); while(pstu != null) { if(pstu->num == stuid) { pstuarr[count++] = pstu; break; } pstu = pstu->pnext; } } else if(order == 2) { printf("请输入要修改的学生姓名:\n"); scanf("%s", name); while(pstu != null) { if(strcmp(pstu->name, name) == 0) { pstuarr[count++] = pstu; if(count % 100 == 0)//如果数组存放满了,则再次申请内存 { pstuarr = (student**)realloc(pstuarr, count + 100); } } pstu = pstu->pnext; } } else { return false; } if(count == 0) { printf("未能找到任何信息,是否继续修改?y/n"); getchar();//过滤掉输入时的换行符 scanf("%c", &yesorno); if(yesorno == 'y' || yesorno == 'y') { system("cls"); showsystemtitle(); return modifystudentinfo(); } } else { printf("为您查找到%d个学生信息:\n ", count); setfontcolor(lightgreen); printf(list_title); setfontcolor(white); for (i = 0; i < count; i++) { printf("%d、%d %s %s %.2f %.2f %.2f\n", i + 1, pstuarr[i]->num, pstuarr[i]->name, pstuarr[i]->sex, pstuarr[i]->score[0], pstuarr[i]->score[1], pstuarr[i]->score[2]); } printf("请输入您要修改的信息序号(1~%d),其他数字返回主菜单\n", count); scanf("%d", &order); if(order >= 1 && order <= count) { printf("请依次输入\n"); setfontcolor(lightgreen); printf(list_title); setfontcolor(white); pstu = pstuarr[order - 1]; scanf("%d %s %s %f %f %f", &pstu->num, pstu->name, pstu->sex, &pstu->score[0], &pstu->score[1], &pstu->score[2]); pstu->averge = (pstu->score[0] + pstu->score[1] + pstu->score[2]) / 3; hasmodify = true; } } free(pstuarr); return hasmodify; } /************************************************************************/ /*检测学号是否存在*/ /************************************************************************/ bool checkstuidexist(int stuid) { student* pstu; pstu = g_pstuhead->pnext; while(pstu != null) { if(pstu->num == stuid) { return true; } pstu = pstu->pnext; } return false; } /************************************************************************/ /*添加学生信息 */ /************************************************************************/ bool addstudentinfo() { printf("输入-1回车,返回上级菜单\n"); setfontcolor(lightgreen); printf(list_title); setfontcolor(white); char c; bool hasadd = false; student* pstu = g_pstuhead; student* pstunew; while (pstu->pnext != null) { pstu = pstu->pnext; } while(1) { pstunew = (student*)malloc(sizeof(student)); scanf("%d", &pstunew->num); if(pstunew->num == -1)//输入-1返回主菜单 { while ((c = getchar()) != eof && c != '\n');//不停地使用getchar()获取缓冲中字符,直到获取的c是“\n”或文件结尾符eof为止 free(pstunew); return hasadd; } else if(checkstuidexist(pstunew->num)) { while ((c = getchar()) != eof && c != '\n');//不停地使用getchar()获取缓冲中字符,直到获取的c是“\n”或文件结尾符eof为止 printf("该学号已存在,请重新输入!\n"); free(pstunew); continue; } hasadd = true; scanf("%s %s %f %f %f", pstunew->name, pstunew->sex, &pstunew->score[0], &pstunew->score[1], &pstunew->score[2]); pstunew->averge = (pstunew->score[0] + pstunew->score[1] + pstunew->score[2]) / 3; pstunew->pnext = null; pstu->pnext = pstunew; pstu = pstunew; } return hasadd; } /************************************************************************/ /*根据指令序号执行对应功能 */ /************************************************************************/ bool ordertoexecute(int order) { bool succ; succ = false; if(order != func_save && order != func_autosave && order!= func_export) { system("cls"); showsystemtitle(); } switch (order) { case func_add://添加 { succ = addstudentinfo(); break; } case func_delete://删除 { succ = deletestudentinfo(); break; } case func_modify://修改 { succ = modifystudentinfo(); break; } case func_search://搜索 { searchstudentinfo(); break; } case func_sort://排序 { succ = sortstudentinfo(); break; } case func_save://保存 { succ = savestudentinfo(); if(succ) { gotoxy(42, func_save + 3); setfontcolor(lightgreen); printf("保存成功!"); setfontcolor(white); gotodelete(0, func_exitsystem + 4, 2); gotoxy(0, func_exitsystem + 4); } return false; } case func_autosave://设置自动保存 { g_autostore = ! g_autostore; printautostoreinfo(); ordertoexecute(func_save);//保存配置 break; } case func_vote://投票系统 { votesystem(); break; } case func_export://导出所有学生信息(明文) { succ = exportstudentinfo(); gotoxy(17, func_export + 3); setfontcolor(lightgreen); if(succ) { printf("导出成功!"); } else { printf("导出失败!"); } setfontcolor(white); gotodelete(0, func_exitsystem + 4, 2); gotoxy(0, func_exitsystem + 4); return false; } default: { break; } } return succ; } int main(int argc, char* argv[]) { int order; bool succ; system("title 学生管理系统 by 机智蛋"); order = 0; succ = false; g_pstuhead = (student*)malloc(sizeof(student)); g_pstuhead->pnext = null; loadstudentinfo(); while(1) { if(order != func_save && order != func_autosave && order != func_export)//当输入这几个指令时不需要初始化屏幕 { initscreen(); } if(succ && order != func_save && g_autostore)//执行自动保存 { ordertoexecute(func_save); } succ = false; do { scanf("%d", &order); if(order >= func_add && order <= func_exitsystem) { break; } else { printf("指令错误,请重新输入\n"); } } while (1); if(order == func_exitsystem)//退出 { printf("欢迎下次继续使用,拜拜~~\n"); return 0; } succ = ordertoexecute(order);//执行功能 } return 0; }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。