数据结构——实验八·学生管理系统

news2025/1/25 1:04:02

嗨~~欢迎来到Tubishu的博客🌸如果你也是一名在校大学生,正在寻找各种编程资源,那么你就来对地方啦🌟
Tubishu是一名计算机本科生,会不定期整理和分享学习中的优质资源,希望能为你的编程之路添砖加瓦⭐🔥
当然,如果你也好的资源推荐,欢迎在评论区分享,让我们共同打造一个丰富的编程资源库🔥🔥🔥
本文专栏 ➡️ 数据结构

学生管理系统

本实验是基于C结构体链表实现学生信息管理,包括添加、修改、删除、查询、按学号输出等基本操作

实验目的:

理解并掌握链表、栈、队列等基本数据结构的特点和应用场景。通过实际编程掌握链表在动态数据结构管理中的优势。
设计并实现一个功能完善的学生信息管理系统,能够进行添加、删除、修改、查询等基本操作。


实验内容:

本次实验要求设计并实现一个学生信息管理系统,具体需求如下:
增加学生信息:允许用户输入学生的基本信息(学号、姓名)并将其添加到系统中。
删除学生信息:根据学号删除指定的学生信息。
修改学生信息:根据学号修改指定学生的信息。
查询学生信息:根据学号查询并显示学生的信息。
统计学生人数:统计系统中学生人数。
显示所有学生信息:列出系统中所有学生的信息。


实验产出:

1.核心代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>

#define NO_LENGTH  20
#define NAME_LENGTH 11

/* 定义学生结构体的数据结构 */
typedef struct Student{
    char studentNo[NO_LENGTH];
    char studentName[NAME_LENGTH];
} st;

/* 定义每条记录或节点的数据结构 */
typedef struct node {
    struct Student data; // 数据域
    struct node *next; // 指针域
} Node, *Link;  // Node为node类型的别名, Link为node类型的指针别名

void inputStudent(Link l){
    printf("请输入学生学号:");
    scanf("%19s", l->data.studentNo); // 防止缓冲区溢出
    printf("请输入学生的姓名:");
    scanf("%10s", l->data.studentName); // 防止缓冲区溢出

    // 每个新创建的节点的next域都初始化为NULL
    l->next = NULL;
}

void inputStudentNo(char s[], char no[]){
    printf("请输入要%s的学生学号:", s);
    scanf("%19s", no); // 防止缓冲区溢出
}

/* 显示学生记录 */
bool displayNode(Link head){
    Link p = head->next;
    while (p != NULL) {
        printf("学号:%s 姓名:%s\n", p->data.studentNo, p->data.studentName);
		p = p->next;
    }
    if (head->next == NULL) 
    	return false;
return true; 
}

/* 增加学生记录 */
bool addNode(Link head){
    Link p, q;
    Link node = (Link)malloc(sizeof(Node));
    if (node == NULL) {
        printf("内存分配失败。\n");
        return false;
    }
    inputStudent(node);

    q = head;
    p = head->next;
    if (head->next == NULL) {
        // 链表为空时
        head->next = node;
    } else {
        // 循环访问链表中的所有节点
        while (p != NULL) {
            if (strcmp(node->data.studentNo, p->data.studentNo) < 0) {
                // 如果node节点的学号比p节点的学号小,则插在p的前面,完成插入后,提前退出子程序
                q->next = node;
                node->next = p;
                return true;
            } else {
                // 如果node节点的学号比p节点的学号大,继续向后移动指针(依然保持q p一前一后)
                q = p;
                p = p->next;
            }
        }
        // 如果没能提前退出循环,则说明之前没有插入,那么当前node节点的学号是最大值,此时插在链表的最后面
        q->next = node;
    }
    return true;
}

/* 删除学生记录 */
bool deleteNode(Link head){
    char no[NO_LENGTH];
    inputStudentNo("删除", no);

    Link p = head, q = head;
    while (p->next != NULL && strcmp(p->next->data.studentNo, no) != 0) {
        q = p;
        p = p->next;
    }
    if (p->next != NULL && strcmp(p->next->data.studentNo, no) == 0) {
        Link temp = p->next;
        p->next = p->next->next;
        free(temp);
        return true;
    }
    return false;
}

/* 查询学生记录 */
bool queryNode(Link head){
    char no[NO_LENGTH];
    inputStudentNo("查询", no);

    Link p = head->next;
    while (p != NULL) {
        if (strcmp(p->data.studentNo, no) == 0) {
            printf("学号:%s 姓名:%s\n", p->data.studentNo, p->data.studentName);
            return true;
        }
        p = p->next;
    }
    return false;
}

/* 修改学生记录 */
bool modifyNode(Link head){
    char no[NO_LENGTH];
    inputStudentNo("修改", no);

    Link p = head->next;
    while (p != NULL) {
        if (strcmp(p->data.studentNo, no) == 0) {
            printf("请输入新的姓名:");
            scanf("%10s", p->data.studentName); // 防止缓冲区溢出
            return true;
        }
        p = p->next;
    }
    return false;
}

/* 统计学生人数 */
int countNode(Link head){
    Link p = head->next;
    int count = 0;
    while (p != NULL) {
        count++;
        p = p->next;
    }
    return count;
}

/* 清除链表 */
void clearLink(Link head){
    Link p, q;
    p = head->next;
    while (p != NULL) {
        q = p->next;
        free(p);
        p = q;
    }
    free(head);
}

// 显示菜单
void myMenu() {
	printf("\n\n\n"); 
    printf("\t*            --菜单--            *\n");
    printf("\t**********************************\n");
    printf("\t*    1---------增加学生记录      *\n");
    printf("\t*    2---------删除学生记录      *\n");
    printf("\t*    3---------查询学生记录      *\n");
    printf("\t*    4---------修改学生记录      *\n");
    printf("\t*    5---------统计学生人数      *\n");
    printf("\t*    6---------显示学生记录      *\n");
    printf("\t*    7---------退出系统          *\n");
    printf("\t**********************************\n");
    
}

int Stu() {
    int select;
    int count;
    int num;
    Link head;  // 定义链表

    // 建立head头结点,在这个程序中head指向头结点,头结点data部分没有内容,其后续节点才有真正的数据
    head = (Link)malloc(sizeof(Node));
    if (head == NULL) {
        printf("内存分配失败。\n");
        return 1;
    }
    head->next = NULL;

    while (1) {
        // myMenu();
        printf("请输入你的选择(1-7):");  // 显示提示信息
        scanf("%d", &select);
        switch (select) {
            case 1:
                // 增加学生记录
                printf("请输入需要添加的学生个数:");
                scanf("%d", &num);
                int n = num;
                while(num) {
                	addNode(head);
                	num--;
				}
                if (!num)
                    printf("成功插入%d个学生记录。\n\n", n);
                else
                    printf("插入学生记录失败。\n\n");
                break;
            case 2:
                // 删除学生记录
                if (deleteNode(head))
                    printf("成功删除一个学生记录。\n\n");
                else
                    printf("没有找到要删除的学生节点。\n\n");
                break;
            case 3:
                // 查询学生记录
                if (queryNode(head))
                    printf("成功找到学生记录。\n\n");
                else
                    printf("没有找到要查询的学生节点。\n\n");
                break;
            case 4:
                // 修改学生记录
                if (modifyNode(head))
                    printf("成功修改一个学生记录。\n\n");
                else
                    printf("没有找到要修改的学生节点。\n\n");
                break;
            case 5:
                // 统计学生人数
                count = countNode(head);
                printf("学生人数为:%d\n\n", count);
                break;
            case 6:
                // 显示学生记录
                // displayNode(head);
                if(displayNode(head))
					printf("\n");
                else
                	printf("链表为空,没有学生记录。\n\n");
                break;
            case 7:
                // 退出前清除链表中的所有结点
                clearLink(head);
                printf("\t成功清除系统并退出!");
                return 0;
            default:
                printf("输入不正确,应该输入1-7之间的数。\n\n");
                break;
        }
    }
    return 0;
}

int main() {
myMenu();
Stu();
}

2.运行结果:
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

3.调试:
显示添加0个记录的空系统、删除系统中不存在的学生记录、查询系统中不存在的学生记录、修改系统中不存在的学生记录等错误调试结果等待你亲自探索哦🤟

请添加图片描述

如果你觉得这篇文章对你有所启发,请为博客点赞👍、收藏⭐️、评论💬或分享🔗,你的支持是Tubishu不断前行的源泉✨!衷心感谢你的鼓励与陪伴🙏!
若你有任何疑问、见解或补充,欢迎随时留言💬,让我们在交流中共同成长📚!❤️
愿各位大佬们在技术的道路上,代码顺畅无阻💻,思路清晰如光💡,不断突破自我,向着更高的目标迈进,实现自己的梦想!🎉
再次感谢你的阅读🌸

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

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

相关文章

【C++篇】红黑树封装 实现map和set

目录 前言&#xff1a; 一&#xff0c;库中map和set的大致结构 二&#xff0c;模拟实现 2.1&#xff0c;大致框架 2.2&#xff0c;复用红黑树实现insert接口 2.3&#xff0c;迭代器iterator的实现 operator()的实现&#xff1a; operator--()的实现&#xff1a; 对inser…

解决CentOS9系统下Zabbix 7.2图形中文字符乱码问题

操作系统&#xff1a;CentOS 9 Zabbix版本&#xff1a;Zabbix7.2 问题描述&#xff1a;主机图形中文字符乱码 解决方案&#xff1a; # 安装字体配置和中文语言包 sudo yum install -y fontconfig langpacks-zh_CN.noarch # 检查是否已有中文字体&#xff1a; fc-list :lan…

统计文本文件中单词频率的 Swift 与 Bash 实现详解

网罗开发 &#xff08;小红书、快手、视频号同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…

计算机网络 (57)改进“尽最大努力交付”的服务

前言 计算机网络中的“尽最大努力交付”服务是网络层的一种数据传输方式。这种服务的特点是网络层只负责尽力将数据报从源端传输到目的端&#xff0c;而不保证数据传输的可靠性。 一、标记与分类 为数据分组打上标记&#xff1a; 给不同性质的分组打上不同的标记&#x…

联想电脑怎么设置u盘启动_联想电脑设置u盘启动方法(支持新旧机型)

有很多网友问联想电脑怎么设置u盘启动&#xff0c;联想电脑设置u盘启动的方法有两种&#xff0c;一是通过bios进行设置。二是通过快捷方式启动进入u盘启动。但需要注意有两种引导模式是&#xff0c;一种是uefi引导&#xff0c;一种是传统的leacy引导&#xff0c;所以需要注意制…

Springboot3 自动装配流程与核心文件:imports文件

注&#xff1a;本文以spring-boot v3.4.1源码为基础&#xff0c;梳理spring-boot应用启动流程、分析自动装配的原理 如果对spring-boot2自动装配有兴趣&#xff0c;可以看看我另一篇文章&#xff1a; Springboot2 自动装配之spring-autoconfigure-metadata.properties和spring…

SET alter system reload

目录标题 alter system 只是 写 auto 文件SET & alter system1. **会话级别参数&#xff08;Session-level parameters&#xff09;**2. **系统级别参数&#xff08;System-level parameters&#xff09;**3. **某些特定的超级用户参数**4. **修改时生效的参数**总结&#…

RPC是什么?和HTTP区别?

RPC 是什么&#xff1f;HTTP 是什么&#xff1f; 作为一个程序员&#xff0c;假设我们需要从A电脑的进程发送一段数据到B电脑的进程&#xff0c;我们一般会在代码中使用 Socket 进行编程。 此时&#xff0c;可选性一般就是 TCP 和 UDP 二选一&#xff0c;由于 TCP 可靠、UDP 不…

Y1打卡学习笔记

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客>- **&#x1f356;原作者&#xff1a;K同学啊** yolov5学习 下载源码运行命令查看结果视频检测个人总结 下载源码 地址&#xff1a;https://github.com/ultralytics/yolov5打开cmd后输入&#xff1…

【前端】Hexo 建站指南

文章目录 前言生成站点本地测试部署云端参考 前言 更好的阅读体验&#xff1a;https://blog.dwj601.cn/FrontEnd/Hexo/build-your-own-website-with-hexo/ 笔记记多了&#xff0c;想要分享给同学们一起交流进步&#xff0c;该怎么办&#xff1f;想要搭建一个属于自己的知识库…

【后端开发】字节跳动青训营之Go语言进阶与依赖管理

Go语言进阶与依赖管理 一、Go语言进阶1.1 并发与并行1.2 协程与线程1.3 通道1.3.1 生产消费模型 1.4 并发安全 二、依赖管理 一、Go语言进阶 Go语言一次可以创建上万个协程。 1.1 并发与并行 并发&#xff1a;多程序程序在单核CPU上运行。并行&#xff1a;多程序程序在多核CP…

大模型-本地化部署调用--基于ollama+openWebUI+springBoot

大模型-本地化部署调用–基于ollamaopenWebUIspringBoot 前言 前段时间&#xff0c;啊&#xff0c;可能不是前段时间&#xff0c;过去的2024年吧&#xff0c;大模型这块的内容也是非常火的&#xff0c;各家巨头也开始卷大模型的研发。那么本人呢也在过去的一年中也是用到了一…

RKNN_C++版本-YOLOV5

1.背景 为了实现低延时&#xff0c;所以开始看看C版本的rknn的使用&#xff0c;确实有不足的地方&#xff0c;请指正&#xff08;代码借鉴了rk官方的仓库文件&#xff09;。 2.基本的操作流程 1.读取模型初始化 // 设置基本信息 // 在postprocess.h文件中定义&#xff0c;详见…

H3C-防火墙IPSec配置案例(主模式)

目录 1.IPSec简述:2.IPSec应用场景:3.网络拓扑及说明:4.案例背景:5.网络配置:5.1 基础网络配置:5.1.1 总部防火墙基础配置:5.1.2 分部防火墙基础配置:5.1.3 互联网路由器基础配置:5.1.4 总部服务器基础配置:5.1.5 总部PC基础配置: 5.2 IPSec配置:5.2.1 总部防火墙IPSec配置:5.2…

windows下本地部署安装hadoop+scala+spark-【不需要虚拟机】

注意版本依赖【本实验版本如下】 Hadoop 3.1.1 spark 2.3.2 scala 2.11 1.依赖环境 1.1 java 安装java并配置环境变量【如果未安装搜索其他教程】 环境验证如下&#xff1a; C:\Users\wangning>java -version java version "1.8.0_261" Java(TM) SE Runti…

vim如何显示行号

:set nu 显示行号 :set nonu 不显示行号 &#xff08;vim如何使设置显示行号永久生效&#xff1a;vim如何使相关设置永久生效-CSDN博客&#xff09;

国产编辑器EverEdit - 命令窗口应用详解

1 命令窗口应用详解 1.1 应用场景 有时需要在EverEdit中执行一些命令行工具&#xff0c;甚至想把当前文档做为参数&#xff0c;传递给命令进行一些文本分析&#xff0c;比如&#xff1a;一些常用的文本处理工具&#xff0c;gawk.exe等。 1.2 使用方法 命令窗口的使用在官方手…

Linux C\C++编程-文件位置指针与读写文件数据块

【图书推荐】《Linux C与C一线开发实践&#xff08;第2版&#xff09;》_linux c与c一线开发实践pdf-CSDN博客 《Linux C与C一线开发实践&#xff08;第2版&#xff09;&#xff08;Linux技术丛书&#xff09;》(朱文伟&#xff0c;李建英)【摘要 书评 试读】- 京东图书 Linu…

vue2使用flv.js在浏览器打开flv格式视频

组件地址&#xff1a;GitHub - bilibili/flv.js: HTML5 FLV Player flv.js 仅支持 H.264 和 AAC/MP3 编码的 FLV 文件。如果视频文件使用了其他编码格式就打不开。 flv.vue <template><div><el-dialog :visible.sync"innerVisibleFlv" :close-on-pre…

Linux下Ubuntun系统报错find_package(BLAS REQUIRED)找不到

Linux下Ubuntun系统报错find_package(BLAS REQUIRED)找不到 这次在windows的WSL2中遇到了一个非常奇怪的错误&#xff0c;就是 CMake Error at /usr/share/cmake-3.22/Modules/FindPackageHandleStandardArgs.cmake:230 (message):Could NOT find BLAS (missing: BLAS_LIBRAR…