文末附有全部代码哦💖💖
文末附有全部代码哦~
一、具体问题
1.问题描述:
设计一个简单的歌手比赛绩管理程序,对一次歌手比赛的成绩进行管理,使用链表实现,基本的设计要求如下(不限于此要求):
(1)输入每个选手的数据包括编号、姓名、十个评委的成绩,根据输入计算出总成绩和平均成绩(去掉最高分,去掉最低分)。
(2)显示主菜单如下:
- 1.选手数据输入
- 2.评委打分
- 3.成绩排序
- 4.数据查询
- 5.追加选手数据
- 6.删除选手数据
- 7.修改选手数据
- 8.输出全部选手信息
- 9.写入数据文件
- 10.退出系统
2.问题来源
当下,无论是校园内还是在社会生活中,经常会举行一些歌手演唱比赛,在信息化的时代里,不会再像以前那样用笔和纸记录比赛的赛况,歌手比赛系统应运而生。歌手比赛系统包含了一切歌手演唱比赛需要的功能,歌手信息的输入,评委打分,成绩排序等功能操作简单高效,可以完成很多繁琐的工作,完全可以满足一切歌手比赛的需求。开发此系统只为方便歌手演唱比赛的举办。
3.解决手段
歌手比赛系统是一个可以储存多个比赛选手信息的系统,主要采用链表来实现存储信息的需求,使用头插法来输入数据,通过选手编号来实现评委打分,成绩排序,数据查询,追加选手数据,删除选手信息,修改选手信息,输出全部选手信息,写入数据文件等功能。
4.应用前景
在信息技术迅速发展的今天,网络对于大多数人已经不再陌生,网络在人们的工作、学习和生活中发挥着不可替代的作用,大大提高了人们生产生活效率。歌手比赛系统是信息技术在人们工作生活中应用的代表,该系统完成评委打分,成绩排序,数据查询,追加选手数据,删除选手信息,修改选手信息,输出全部选手信息,写入数据文件等功能,这些功能可以让评委们在歌手比赛结算时时更加方便快捷。同时,该系统也可以应用到其他比赛当中,使比赛更加方便快捷。
二、需求分析
1.功能需求分析
歌手比赛系统是我们为了方便进行歌手比赛而开发的一套系统,该系统的主要目的是实现选手的信息分析,该系统具有评委打分,成绩排序,数据查询,追加选手数据,删除选手信息,修改选手信息,输出全部选手信息,写入数据文件等功能。同时,歌手比赛系统基于c语言编译的源程序,其调用函数根据所需要模块进行引用,再编写好之后,要对程序进行相应的调试,以验证程序的正确性和可用性。调试及测试时,通过相应信息,充分证明程序的可行性,同时本程序具有很高的逻辑性和严密性。
2.系统功能模块图
该程序的系统功能模块图如下图所示。
3.数据结构定义
typedef struct Node { int id;//编号 char name[MAXSIZE];//姓名 float grade[NUMBER];//评委评分 float sum;//总分 float average;//平均分 struct Node \*next;//指针域 } S;//结构体定义为S //各函数定义 void menu(); //菜单函数 S \*create();//创建链表函数 void print(S \*);//输出链表函数 void insert(S \*);//插入节点函数 void del(S \*);//删除节点函数 void update(S \*); void search(S \*);//查找节点函数 void sort(S \*);//节点排序函数 void save(S \*); void giveScore(S \*);
三、系统设计
1.主要函数表
2.功能流程图
(1)添加选手信息
如下图所示:
(2)修改选手信息
如下图所示:
(3)删除选手信息
如下图所示:
四、代码测试
1.主函数
//主函数 int main() { S \*head; int n, a = 1;//n用来控制选择操作类型,a控制循环,以-1终止 while (a > 0) { menu();//显示菜单 printf("请输入操作数:"); scanf("%d", &n);//选择操作 switch (n)//各操作数字对应菜单数字,通过n确定操作类型 { //创建结点,输入选手数据 case 1: head = create(); break; //评委打分 case 2: if (head == NULL) { printf("链表为空,请先执行1操作!\n"); break; } giveScore(head); break; //排序 case 3: if (head == NULL) { printf("链表为空,请先执行1操作!\n"); break; } sort(head); break; //查询 case 4: if (head == NULL) { printf("链表为空,请先执行1操作!\n"); break; } search(head); break; //追加数据 case 5: if (head == NULL) { printf("链表为空,请先执行1操作!\n"); break; } insert(head); break; //删除 case 6: if (head == NULL) { printf("链表为空,请先执行1操作!\n"); break; } del(head); break; //修改数据 case 7: if (head == NULL) { printf("链表为空,请先执行1操作!\n"); break; } update(head); break; //输出全部选手信息 case 8: if (head == NULL) { printf("链表为空,请先执行1操作!\n"); break; } print(head); break; //写入文件 case 9: if (head == NULL) { printf("链表为空,请先执行1操作!\n"); break; } save(head); break; //退出系统 case 0: exit(0); break; default: printf("退出系统"); a = -1;//跳出循环条件 break; } } return 0; }
2.菜单模块
//菜单模块直接显示 void menu() { printf("==============================\n"); printf("=========请选择操作============\n"); printf("========1.输入选手数据=========\n"); printf("========2.评委打分============\n"); printf("========3.成绩排序============\n"); printf("========4.数据查询============\n"); printf("========5.追加选手数据=========\n"); printf("========6.删除选手信息=========\n"); printf("========7.修改选手信息=========\n"); printf("========8.输出全部选手信息======\n"); printf("========9.写入数据文件=========\n"); printf("========0.退出系统============\n"); printf("=============================\n"); }
- 运行结果如下:
3.输入选手数据模块
//1.输入选手数据 S \*create() { S \*head, \*p, \*q;//定义指针 int i; head = (S \*) malloc(sizeof(S));//头节点开辟空间 head->average = 0;//置空头节点的average成员 head->next = NULL;//置空头节点的指针域 q = head;//q指针记录头节点的地址 p = head->next;//p指针记录头节点的指针域的地址 printf("请输入选手编号和姓名(编号为0则表示停止):\n"); int id; printf("请输入选手id(输入0退出):\n"); scanf("%d", &id); while (id != 0)//输入选手编号输入为零停止循环 { p = (S \*) malloc(sizeof(S));//p指针开辟空间 p->id = id; printf("请输入选手姓名:\n"); scanf("%s", p->name); for (i = 0; i < NUMBER; i++) { p->grade[i] = 0; } p->sum = 0; p->average = 0; p->next = NULL;//置空p节点的指针域 q->next = p;//p,q节点连接 q = p;//q指针后移 printf("请输入选手id(输入0退出):\n"); scanf("%d", &id); } return head;//返回链表的起始地址 }
- 运行结果如下:
4.评委打分模块
//2.评委打分 void giveScore(S \*head) { //定义指针 S \*p; p = head->next; float max, min; while (p != NULL) { if (p->grade[0] != 0) { p = p->next; continue; } printf("请十位评为给编号为%d的选手打分:\n", p->id); p->sum = 0; for (int i = 0; i < NUMBER; i++) { printf("请第%d位评委打分:", i); scanf("%f", &p->grade[i]); p->sum += p->grade[i]; } printf("\n"); min = max = p->grade[0]; for (int i = 0; i < NUMBER; i++) { if (p->grade[i] > max) max = p->grade[i]; if (p->grade[i] < min) min = p->grade[i]; } p->average = (p->sum - max - min) / 8; p = p->next; } }
- 运行结果如下:
5.按照平均成绩排序 – 采用冒泡排序,交换节点
//3.按照平均成绩排序 -- 采用冒泡排序,交换节点 void sort(S \*head) { S \*p, \*pre, \*temp, \*tail; tail = NULL; // 算法的核心部分,节点交换 while (head->next != tail) { pre = head; p = head->next; while (p->next != tail) { if (p->average < p->next->average) { temp = p->next; pre->next = p->next; p->next = p->next->next; pre->next->next = p; p = temp; } // 节点后移 p = p->next; pre = pre->next; } tail = p; } }
6.数据查询模块
//4.根据id查找节点模块 void search(S \*head) { S \*p;//定义指针 int id;//定义b用于输入查找编号 printf("请输入要查找的选手编号:"); //输入查找编号 scanf("%d", &id); p = head->next; while (p != NULL) { if (p->id == id)//判断是否找到选手编号 { //为真时,输出信息 printf("编号\t姓名\t\t\t\t\t十位评委的成绩\t\t\t\t\t总成绩\t平均成绩\n"); printf("%d %s %.2f%.2f%.2f%.2f%.2f%.2f%.2f%.2f%.2f%.2f %.2f %.2f\n", p->id, p->name, p->grade[0], p->grade[1], p->grade[2], p->grade[3], p->grade[4], p->grade[5], p->grade[6], p->grade[7], p->grade[8], p->grade[9], p->sum, p->average); break; } else //为假时 p = p->next;//指针后移 } if (p == NULL)//查找到最后一个节点还未查到要的编号时,输出ERROR INPUT printf("输入的选手编号错误\n"); }
- 运行结果如下:
7.追加选手数据模块
//5.追加节点模块(可多个插入) void insert(S \*head) { int i, id, flag = 1;//flag实现判断指针是否到达最后一个节点 S \*p, \*q, \*r; //定义指针便于插入操作 p = head; printf("请输入选手信息:\n"); printf("请输入选手id(输入0退出):\n"); scanf("%d", &id); while (id != 0)//输入编号不为零时循环,以零终止,可实现多个插入 { r = (S \*) malloc(sizeof(S));//为r开辟空间 r->next = NULL;//置空r的指针域 //输入相关数据,并计算相关数据 r->id = id; printf("请输入选手姓名:\n"); scanf("%s", r->name); r->sum = 0; r->average = 0; for (i = 0; i < NUMBER; i++) { r->grade[i] = 0; } while (p->next != NULL) { p = p->next; } p->next = r; printf("请输入选手id(输入0退出):\n"); scanf("%d", &id); } }
- 运行结果如下:
8.删除选手信息模块
//6.删除节点模块 void del(S \*head) { S \*p, \*q;//定义指针 int b;//用于输入编号查找删除 p = head;//p记录头节点的地址 q = head->next;//q记录头节点的指针域的地址 printf("请输入要删除选手的id:"); //输入编号 scanf("%d", &b); while (q != NULL)//q不为空时执行循环 { if (q->id == b)//判断是否找到输入的编号 //为真时 { p->next = q->next;//断开q节点 free(q);//释放q节点neicun q = NULL; //置空q指针防止出现野指针 } else { //判断为假时 p = p->next;//p指针后移 q = q->next;//q指针后移 } } if (p == NULL)//当查找到最后一个节点还未查到要删除的编号时,输出ERROR INPUT printf("输入的选手id不存在!\n"); }
- 运行结果如下:
9.修改选手信息模块
//修改选手信息 void update(S \*head) { S \*p, \*q, \*new;//定义指针 int id;//用于输入编号查找删除 float min = 999, max = 0; p = head;//p记录头节点的地址 q = head->next;//q记录头节点的指针域的地址 printf("请输入要修改的选手id:"); //输入编号 scanf("%d", &id); while (q != NULL)//q不为空时执行循环 { //判断是否找到输入的编号 if (q->id == id) { new = (S \*) malloc(sizeof(S)); printf("请输入%d号选手的新成绩:", q->id); new->id = q->id; strcpy(new->name, q->name); new->sum = 0; new->average = 0; for (int i = 0; i < NUMBER; ++i) { scanf("%f", &new->grade[i]); new->sum += new->grade[i]; if (new->grade[i] > max) { max = new->grade[i]; } if (new->grade[i] < min) { min = new->grade[i]; } } new->average = (new->sum - max - min) / (NUMBER - 2); new->next = q->next;//断开q节点 p->next = new; free(q);//释放q节点 q = NULL; //置空q指针防止出现野指针 } else { //判断为假时 p = p->next;//p指针后移 q = q->next;//q指针后移 } } if (p == NULL)//当查找到最后一个节点还未查到要修改的编号时 printf("输入的选手id不存在!\n"); }
- 运行结果如下:
10.输出全部选手信息模块
//7.输出全部选手信息 void print(S \*head) { int i; S \*p = head->next; printf("编号\t姓名\t总成绩\t平均成绩\t\t\t\t\t十位评委的成绩\t\t\t\t\n"); while (p)//当p不为空的时候执行 { printf("%-d\t%-s\t%-.2f\t%-.2f\t", p->id, p->name, p->sum, p->average); for (i = 0; i < NUMBER; i++) printf("%-6.2f\t", p->grade[i]); printf("\n"); p = p->next;//指针后移 } }
- 运行结果如下:
11.写入数据文件(记得修改写入文件地址)
//8.写入数据文件 void save(S \*head) { S \*p; p = head->next; FILE \*fp; if ((fp = fopen("C:\\Users\\zhuxuanyu\\Desktop\\file.txt", "wt")) == NULL) { printf("打开写入文件fle.txt失败\n"); return; } while (p) { fprintf(fp, "编号:%-d\t 姓名:%-s\t 总成绩:%-.2f\t 平均成绩:%-.2f\t 评委打分:", p->id, p->name, p->sum, p->average); for (int i = 0; i < NUMBER; ++i) { fprintf(fp, "%-.2f\t", p->grade[i]); } fprintf(fp, "\n"); p = p->next; } fclose(fp); }
五、完整代码
#include
#include #include //创建结构体及其成员 #define MAXSIZE 20 #define NUMBER 10 typedef struct Node { int id;//编号 char name[MAXSIZE];//姓名 float grade[NUMBER];//评委评分 float sum;//总分 float average;//平均分 struct Node \*next;//指针域 } S;//结构体定义为S //各函数定义 void menu(); //菜单函数 S \*create();//创建链表函数 void print(S \*);//输出链表函数 void insert(S \*);//插入节点函数 void del(S \*);//删除节点函数 void update(S \*); void search(S \*);//查找节点函数 void sort(S \*);//节点排序函数 void save(S \*); void giveScore(S \*); //主函数 int main() { S \*head; int n, a = 1;//n用来控制选择操作类型,a控制循环,以-1终止 ![img](https://img-blog.csdnimg.cn/img_convert/ee864a13836278a5a3af92094dd81490.png) ![img](https://img-blog.csdnimg.cn/img_convert/dde37275d9aa96dd1074cff79b42f432.png) **网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。** **[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)** **一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!** oid menu(); //菜单函数 S \*create();//创建链表函数 void print(S \*);//输出链表函数 void insert(S \*);//插入节点函数 void del(S \*);//删除节点函数 void update(S \*); void search(S \*);//查找节点函数 void sort(S \*);//节点排序函数 void save(S \*); void giveScore(S \*); //主函数 int main() { S \*head; int n, a = 1;//n用来控制选择操作类型,a控制循环,以-1终止 [外链图片转存中...(img-CJfvvSnZ-1714457783062)] [外链图片转存中...(img-eAeh9wQm-1714457783063)] **网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。** **[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)** **一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
- 运行结果如下:
- 运行结果如下:
- 运行结果如下:
- 运行结果如下:
- 运行结果如下:
- 运行结果如下:
- 运行结果如下:
- 运行结果如下: