C语言实现学生成绩管理系统(单链表)

本次我就用学到的相关链表知识总结回顾一下学生成绩管理系统的实现

首先还是先创建一个项目,分别创建头文件和源文件,头文件用来声明函数,源文件用来定义函数以及实现学生成绩管理系统。

创建完成后如上图。

先创建一个结构体用来存放学生信息(学号,姓名,成绩),在这里学号我使用的是字符数组,整型可能不能满足学号长度的需要。

//学生信息
typedef struct student
{char number[15];char name[20];float score;
}stu;

接着就是创建节点用来链接学生信息喽!节点如下:常规的放一个结构体(学生信息)以及下一个结点的地址。

//节点信息
typedef struct Node
{stu student;struct Node* next;
}node;

基本步骤就完成了。接下来是菜单,用来指引用户完成程序。菜单就用函数来实现(记得先在头文件里声明)。

void menu()
{printf("\t*****************学生成绩管理系统***************\n");printf("\t**************请选择功能列表********************\n");printf("\t*******1.添加学生信息  2.打印学生信息*******\n");printf("\t*******3.统计学生人数  4.查找学生信息*******\n");printf("\t*******5.修改学生信息  6.删除学生信息*******\n");printf("\t*******7.按成绩排序    8.退出系统***********\n");
}

菜单里的东西就是学生成绩系统将要完成的操作了。接下来我会详细说明每个步骤的实现。

1.添加学生信息

同样用函数实现,为了方便实现链表的增删查改,需要使用一个头结点,头结点里不存放任何东西,只是方便链表操作,添加学生生信息即为给链表尾插一个新的节点,添加节点要注意的是要先向内存申请空间,因为申请的是节点空间,所以就要用结构体指针(节点地址)来接收,之后初始化新建节点,用scanf输入要添加的学生信息,之后就要进行尾插操作了,判断是否只有一个节点,若是,则直接将头结点的next指向新节点,若不是,找到尾结点,这就需要引出一个新节点用来找尾结点,循环遍历cur直至到最后一个节点,将最后一个节点指向新建节点即可。

void inputstudent(node* head)
{node* fresh = (node*)malloc(sizeof(node));fresh->next = NULL;printf("请输入学生的学号、姓名、成绩:");scanf("%s%s%f", fresh->student.number, fresh->student.name, &fresh->student.score);if(head->next==NULL)head->next = fresh;else{node*cur = head;while (cur->next != NULL){cur = cur->next;}cur ->next= fresh;}
}

2.打印学生信息

打印学生信息也是需要一个可移动节点对链表进行遍历,依次打印即可。

void printstudent(node* head)
{node* cur = head;while (cur->next != NULL){printf("学号:%s 姓名:%s 成绩:%.2f\n", cur->next->student.number, cur->next->student.name, cur->next->student.score);cur = cur->next;}
}

3.统计学生人数

统计人数就是在遍历链表的过程中引入一个变量进行计数即可。

void countstudent(node* head)
{int count = 0;node* cur = head;while (cur->next != NULL){count++;cur = cur->next;}printf("学生的总人数为:%d\n", count);
}

4.查找学生信息

查找学生信息时是通过学生的学号找出学生的各项信息,由于要让用户输入要查找的学生的学号,故要定义一个字符数组,之后将节点里的学生信息里的学号依次与用户输入的信息进行比较,比对成功输入该项学生的各项信息即可,比较时,由于是字符串之间的比较,所以要用到字符串比较函数strcmp,不可直接用”==“.

void findstudent(node* head)
{char stu[20];printf("请输入要查找的学生的学号:");scanf("%s", stu);node* cur = head;while (cur->next != NULL){if (strcmp(cur->next->student.number,stu) == 0){printf("学号:%s 姓名:%s 成绩:%.2f\n", cur->next->student.number, cur->next->student.name, cur->next->student.score);return;}cur = cur->next;}printf("未找到该学生\n");
}

使学生信息更持久化

这个操作涉及到文件操作,先出 创建或打开文件(fopen),再向文件中写入数据(fwrite),遍历链表将每个节点保存到文件中。将该函数放置在添加学生信息的函数后即可。

void savestudent(node* head)
{FILE* file = fopen("./stu.info", "w");//w即write可写node* cur = head;while (cur->next != NULL){if (fwrite(&cur->next->student, sizeof(stu), 1, file) != 1)//fwrite(要写入文件的数据的地址,数据的字节大小,传入数据的个数,传入的目标文件){printf("写入失败\n");return;}cur = cur->next;}fclose(file);//关闭文件
}

读取文件

打开之前存放过数据的文件,读取文件中的每个学生信息,将其连接到新链表中,用可移动的节点从头结点开始循环,先申请一个空间用来存放读取的第一个节点,之后将可移动节点的next链接到读取的数据存放的新申请空间的节点,可移动节点向后遍历,继续申请空间。直至文件中的数据全部被读取。注意最后要释放掉最后一次申请的空间,循环之前已经申请过一次空间,最后一次循环中申请的空间未被利用到。

void loadstudent(node* head)
{FILE* file = fopen("./stu.info", "r");//r即read只读if (!file){printf("没有学生文件,跳过读取\n");return;}node* fresh = (node*)malloc(sizeof(node));node* cur = head;                        fresh->next = NULL;while (fread(&fresh->student, sizeof(stu), 1, file) == 1)//fread(读取出的数据存放的地址,读取出数据的字节大小,读取出数据的个数,读取数据的来源){cur->next = fresh;cur = fresh;fresh = (node*)malloc(sizeof(node));fresh->next = NULL;}free(fresh);fclose(file);printf("读取成功!\n");
}

5.修改学生信息

此操作和查找学生信息有点相似,先让用户输入要修改的学生的学号,再循环遍历查找此学生修改即可,记得修改完成后将其存到文件中。

void modifystudent(node* head)
{printf("请输入要修改的学生的学号:");char stu[15];scanf("%s", stu);node* cur = head->next;while (cur != NULL){if (strcmp(cur->student.number, stu) == 0){printf("请输入学生姓名,成绩:");scanf("%s%f", cur->student.name, &cur->student.score);savestudent(head);//持久化学生信息printf("修改成功\n");return;}cur = cur->next;}printf("未找到该学生\n");
}

6.删除学生信息

先找到要删除的学生,注意要使用的是删除学生的前一个节点,将前一个节点与删除学生的下一个节点链接起来,删除学生的节点就不在链表中了,释放掉删除学生的空间即可。注意:不可直接将该节点删除,否则删除学生后面的节点就无法找到。

void deletestudent(node* head)
{printf("请输入要删除的学生的学号:");char stu[15];scanf("%s", stu);node* cur = head;while (cur->next!=NULL){if (strcmp(stu, cur->next->student.number) == 0){node* tmp = cur->next;//记录删除的学生节点cur->next = cur->next->next;free(tmp);tmp = NULL;savestudent(head);printf("删除成功\n");return;}cur = cur->next;}printf("未找到该学生\n");
}

7.根据学生成绩将学生进行排序

用冒泡排序对链表中的节点的数据进行排序(链表中结点的数据即为学生信息,直接交换学生信息即可,不用交换节点)。

结点的冒泡排序:

void sortstudent(node* head)
{node* save = NULL;node* cur = NULL;for (node* turn = head->next; turn->next != NULL;turn=turn->next){for ( cur = head->next; cur->next != save; cur = cur->next){if (cur->next->student.score < cur->student.score){stu temp = cur->student;cur->student = cur->next->student;cur->next->student = temp;}}save = cur;//简化比较次数,最后面已经排序过的数据就不用再进行比较}printstudent(head);
}

整体代码如下:

StudentSystem.h: 


#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<string.h>
//学生信息
typedef struct student
{char number[15];char name[20];float score;
}stu;
//节点信息
typedef struct Node
{stu student;struct Node* next;
}node;
void menu();
//输入学生信息
void inputstudent(node* head);
//打印学生信息
void printstudent(node* head);
//统计学生人数
void countstudent(node* head);
//查找学生信息
void findstudent(node* head);
//使学生信息持久化 写入文件
void savestudent(node* head);
//读取文件
void loadstudent(node* head);
//修改学生信息
void modifystudent(node* head);
//删除学生信息
void deletestudent(node* head);
//按照学生成绩排序
void sortstudent(node* head);

StudentStystem.c: 

#include"StudentStystem.h"
void menu()
{printf("\t*****************学生成绩管理系统***************\n");printf("\t**************请选择功能列表********************\n");printf("\t*******1.添加学生信息  2.打印学生信息*******\n");printf("\t*******3.统计学生人数  4.查找学生信息*******\n");printf("\t*******5.修改学生信息  6.删除学生信息*******\n");printf("\t*******7.按成绩排序    8.退出系统***********\n");
}
void inputstudent(node* head)
{node* fresh = (node*)malloc(sizeof(node));fresh->next = NULL;printf("请输入学生的学号、姓名、成绩:");scanf("%s%s%f", fresh->student.number, fresh->student.name, &fresh->student.score);if(head->next==NULL)head->next = fresh;else{node*cur = head;while (cur->next != NULL){cur = cur->next;}cur ->next= fresh;}savestudent(head);
}
void printstudent(node* head)
{node* cur = head;while (cur->next != NULL){printf("学号:%s 姓名:%s 成绩:%.2f\n", cur->next->student.number, cur->next->student.name, cur->next->student.score);cur = cur->next;}
}
void countstudent(node* head)
{int count = 0;node* cur = head;while (cur->next != NULL){count++;cur = cur->next;}printf("学生的总人数为:%d\n", count);
}
void findstudent(node* head)
{char stu[20];printf("请输入要查找的学生的学号:");scanf("%s", stu);node* cur = head;while (cur->next != NULL){if (strcmp(cur->next->student.number,stu) == 0){printf("学号:%s 姓名:%s 成绩:%.2f\n", cur->next->student.number, cur->next->student.name, cur->next->student.score);return;}cur = cur->next;}printf("未找到该学生\n");
}
void savestudent(node* head)
{FILE* file = fopen("./stu.info", "w");//w即write可写node* cur = head;while (cur->next != NULL){if (fwrite(&cur->next->student, sizeof(stu), 1, file) != 1)//fwrite(要写入文件的数据的地址,数据的字节大小,传入数据的个数,传入的目标文件){printf("写入失败\n");return;}cur = cur->next;}fclose(file);//关闭文件
}
void loadstudent(node* head)
{FILE* file = fopen("./stu.info", "r");//r即read只读if (!file){printf("没有学生文件,跳过读取\n");return;}node* fresh = (node*)malloc(sizeof(node));node* cur = head;                        fresh->next = NULL;while (fread(&fresh->student, sizeof(stu), 1, file) == 1)//fread(读取出的数据存放的地址,读取出数据的字节大小,读取出数据的个数,读取数据的来源){cur->next = fresh;cur = fresh;fresh = (node*)malloc(sizeof(node));fresh->next = NULL;}free(fresh);fclose(file);printf("读取成功!\n");
}
void modifystudent(node* head)
{printf("请输入要修改的学生的学号:");char stu[15];scanf("%s", stu);node* cur = head->next;while (cur != NULL){if (strcmp(cur->student.number, stu) == 0){printf("请输入学生姓名,成绩:");scanf("%s%f", cur->student.name, &cur->student.score);savestudent(head);//持久化学生信息printf("修改成功\n");return;}cur = cur->next;}printf("未找到该学生\n");
}
void deletestudent(node* head)
{printf("请输入要删除的学生的学号:");char stu[15];scanf("%s", stu);node* cur = head;while (cur->next!=NULL){if (strcmp(stu, cur->next->student.number) == 0){node* tmp = cur->next;cur->next = cur->next->next;free(tmp);tmp = NULL;savestudent(head);printf("删除成功\n");return;}cur = cur->next;}printf("未找到该学生\n");
}
void sortstudent(node* head)
{node* save = NULL;node* cur = NULL;for (node* turn = head->next; turn->next != NULL;turn=turn->next){for ( cur = head->next; cur->next != save; cur = cur->next){if (cur->next->student.score < cur->student.score){stu temp = cur->student;cur->student = cur->next->student;cur->next->student = temp;}}save = cur;}printstudent(head);
}

test.c :


#include"StudentStystem.h"int main()
{//创建头结点node* head = (node*)malloc(sizeof(node));head->next = NULL;loadstudent(head);menu();while (1){char c = _getch();switch (c){case '1':inputstudent(head);break;case '2':printstudent(head);break;case '3':countstudent(head);break;case '4':findstudent(head);break;case '5':modifystudent(head);break;case '6':deletestudent(head);break;case '7':sortstudent(head);break;case '8':system("cls");printf("欢迎下次使用\n");exit(0);break;default:printf("请重新输入:");break;}}return 0;
}

 学生成绩管理系统到这里就完成啦,该系统与单链表的增删查改关系关系密切。大家想要多了解的话点击以下链接即可。

有关单链表更多接口函数的详细说明:

C语言实现单链表的各个接口函数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/624045.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DaisyDisk for mac 中文激活版 可视化磁盘清理工具

DaisyDisk 是一款专为 Mac 设计的磁盘空间分析工具。它以直观、图形化的方式展示硬盘使用情况&#xff0c;帮助用户迅速找到占用空间大的文件和文件夹。通过扫描磁盘&#xff0c;DaisyDisk 生成彩色的扇形图表&#xff0c;每个扇区代表一个文件或文件夹&#xff0c;大小直观反映…

Java多线程并发篇----第十五篇

系列文章目录 文章目录 系列文章目录前言一、偏向锁二、分段锁三、锁优化四、线程基本方法前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 一、偏向锁 Hotspot 的…

肯尼斯·里科《C和指针》第6章 指针(4)实例

肯尼斯里科《C和指针》第6章 指针&#xff08;1&#xff09;-CSDN博客 肯尼斯里科《C和指针》第6章 指针&#xff08;2&#xff09;-CSDN博客 肯尼斯里科《C和指针》第6章 指针&#xff08;3&#xff09;-CSDN博客 6.12 实例 /* ** 计算一个字符串的长度。 */ #include <…

leetcode 349 两个数组的集合

题目 给定两个数组 nums1 和 nums2 &#xff0c;返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 示例 1&#xff1a; 输入&#xff1a;nums1 [1,2,2,1], nums2 [2,2] 输出&#xff1a;[2] 示例 2&#xff1a; 输入&#xff1a…

【playwright】新一代自动化测试神器playwright+python系列课程00——playwright安装

playwright安装 本文主要分享由微软开发的实现Web UI自动化测试工具Playwright库&#xff0c;相比于之前学习过selenium库&#xff0c;playwright对于编写自动化代码绝对是更轻松了&#xff0c;因为它支持脚本录制&#xff0c;如果只求简单点可以不用写一行代码就能够实现自动…

网络安全|GitHub 已成为恶意软件传播的严重污染源

Recorded Future 凸显了全球合法平台威胁的上升。 根据 Recorded Future最近 的一份报告&#xff0c;开发者平台GitHub最近已成为黑客用来托管和传播恶意软件的流行工具。 该平台为攻击者提供了将其行为伪装成合法网络流量的能力&#xff0c;这使得跟踪和确定攻击者的身份变得…

ubuntu20.04 deepstream 6.3安装

1.基础环境gstreamer sudo apt install \ libssl-dev \ libgstreamer1.0-0 \ gstreamer1.0-tools \ gstreamer1.0-plugins-good \ gstreamer1.0-plugins-bad \ gstreamer1.0-plugins-ugly \ gstreamer1.0-libav \ libgstreamer-plugins-base1.0-dev \ libgstrtspserver-1.0-0 …

C练习——模拟投掷6000次骰子

题目&#xff1a; 模拟骰子投6000次&#xff0c;并计算每一面出现的概率 解析&#xff1a; 6000次&#xff0c;首先想到用数组记录六个面各出现次数 其次&#xff0c;使用随机数&#xff08;1~6的数&#xff09;模拟骰子 然后统计1~6每个数出现的几次&#xff0c;最后除以6…

倒F天线设计经验分享

一、IFA天线理论分析 为了改善&#xff29;&#xff2c;&#xff21;天线难以使用的缺点&#xff0c;在&#xff29;&#xff2c;&#xff21;天线的基础上再增加一个倒L结构&#xff0c;形成IFA天线&#xff0c;此种天线体积小、易于匹配并具有双极化的特点&#xff0c;而在蓝…

基于springboot的二手车交易系统的设计与实现

&#x1f345;点赞收藏关注 → 私信领取本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345;一 、设计说明 1.1 课题背景 二…

交换机批量巡检、配置软件

使用Python3.8实现&#xff0c;支持huawei\h3c\cisco三种交换机批量巡检或者批量配置。 要求&#xff1a;同一种类型的交换机有相同的登录账号和密码&#xff0c;开启ssh服务。 可以查看mac地址是否漂移或者欺骗、ip地址与MAC对应关系&#xff0c;可以查看是否有环路&#xf…

AI 图像自动补全 Uncrop 工具介绍

ClipDrop Uncrop是一款基于AI的图像自动补全工具&#xff0c;由StabilityAI旗下的Clipdrop开发。通过利用StableDiffusionXL开发的算法和深度学习技术&#xff0c;Uncrop可以对用户上传的图片进行自动扩展和补全&#xff0c;改变图片尺寸&#xff0c;使得图像内容得到更完整的呈…

互联网上门洗衣洗鞋工厂系统搭建;

随着移动互联网的普及&#xff0c;人们越来越依赖手机应用程序来解决生活中的各种问题。通过手机预约服务、购买商品、获取信息已经成为一种生活习惯。因此&#xff0c;开发一款上门洗鞋小程序&#xff0c;可以满足消费者对于方便、快捷、专业的洗鞋服务的需求&#xff0c;同时…

MYSQL第三次作业--单表查询

第三次作业 一、创建worker表 mysql> create table worker(-> 部门号 int(11) not null,-> 职工号 int(11) not null,-> 工作时间 date not null,-> 工资 float(8,2) not null,-> 政治面貌 varchar(10) not null default群众,-> 姓名 varchar(20) not n…

【无主之地3】最详细的补丁教程(酸奶公园)

【无主之地3】最详细的补丁教程&#xff08;酸奶公园&#xff09; steam已有游戏 1.迅雷种子下载文件&#xff0c;只用下载AddtionalContent这一个&#xff0c;放在文件夹OakGame下 2.将文件夹Engine&#xff1e;Binaries&#xff1e;ThirdParty&#xff1e;steamworks&a…

人脸识别(Java实现的)

虹软人脸识别&#xff1a; 虹软人脸识别的地址&#xff1a;虹软视觉开放平台—以免费人脸识别技术为核心的人脸识别算法开放平台 依赖包&#xff1a; 依赖包是从虹软开发平台下载的 在项目中引入这个依赖包 pom.xml <!-- 人脸识别 --><dependency><gr…

DeepFloyd IF:由文本生成图像的强大模型,能够绘制文字的 AI 图像工具

文章目录 一、DeepFloyd IF 简介二、DeepFloyd IF模型架构三、DeepFloyd IF模型生成流程四、DeepFloyd IF 模型定义 一、DeepFloyd IF 简介 DeepFloyd IF&#xff1a;能够绘制文字的 AI 图像工具 之前的 Stable Diffusion 和 Midjourney 都无法生成带有文字的图片&#xff0c;…

YOLOv8改进 | 细节涨点篇 | UNetv2提出的一种SDI多层次特征融合模块(分割高效涨点)

一、本文介绍 本问给大家带来的改进机制是UNetv2提出的一种多层次特征融合模块(SDI)其是一种用于替换Concat操作的模块,SDI模块的主要思想是通过整合编码器生成的层级特征图来增强图像中的语义信息和细节信息。该方法已在多个公开的医学图像分割数据集上进行了验证,包括皮…

【数据库原理】(27)数据库恢复

在数据库系统中&#xff0c;恢复是指在发生某种故障导致数据库数据不再正确时&#xff0c;将数据库恢复到已知正确的某一状态的过程。数据库故障可能由多种原因引起&#xff0c;包括硬件故障、软件错误、操作员失误以及恶意破坏。为了确保数据库的安全性和完整性&#xff0c;数…

多合一小程序商城系统源码:支持全平台端口 附带完整的搭建教程

现如今&#xff0c;随着移动互联网的飞速发展&#xff0c;小程序已经成为电商行业的新宠。罗峰给大家分享一款多合一小程序商城系统源码。该系统旨在为商家提供一个功能强大、易于搭建和管理的电商平台&#xff0c;帮助商家快速占领市场&#xff0c;提高品牌影响力。 以下是部…