c入门第十八篇——支持学生数的动态增长(链表,指针的典型应用)

数组最大的问题,就是不支持动态的扩缩容,它是静态内存分配的,一旦分配完成,其容量是固定的。为了支持学生的动态增长,这里可以引入链表。

链表

在C语言中,链表是一种常用的数据结构,它由一系列的节点组成,每个节点包含数据和指向下一个节点的指针。
链表的关键点:

  1. 节点(Node): 链表中的每个元素称为节点。每个节点通常包含两个部分:数据(Data)和指向另一个节点的指针(Next)。
  2. 头指针(Head Pointer):一个指针,它指向链表的第一个节点。这是链表的起点,通过头指针可以遍历整个链表。
  3. 尾节点(Tail Node):链表的最后一个节点,并不是一个独立的指针,而是链表中的一个节点,其指针部分指向NULL,表示链表的结束。
    在这里插入图片描述
    学生信息的结构体可以重新定义为:
typedef struct student {int id; // 学号char name[MAX_NAME_LEN]; // 姓名float score; // 成绩struct student *next; //这里不能够使用 Student *next原因是Student还未定义。
} Student;

链表实现完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define MAX_NAME_LEN 50
#define STUDENT_SYSTEM "student_system"typedef struct student {int id; // 学号char name[MAX_NAME_LEN]; // 姓名float score; // 成绩struct student *next;
} Student;struct student_db {Student *header; // 后续指向学生信息链表头部的指针int student_count; // 学生数量
};struct student_db stu_db = {.header = NULL,.student_count = 0
};int write_student_info(Student *s)
{FILE *fp = fopen(STUDENT_SYSTEM, "a");if (fp == NULL) {printf("fopen student_system failed!\n");return 1;}fprintf(fp, "%-4d %-10s %-.2f\n", s->id, s->name, s->score);fclose(fp);return 0;
}int check_if_student_exsit(int id)
{Student *cur= stu_db.header;while(cur!= NULL) {if(cur->id == id) {return 1;}cur = cur->next;}return 0;
}void add_student()
{Student s, *cur, *tmp_s;printf("Enter student ID: ");scanf("%d", &s.id);printf("Enter student name: ");scanf("%s", s.name);s.score = 0.0; // 初始成绩设置为0if (!check_if_student_exsit(s.id)) {cur = stu_db.header;while(cur) {if (cur->next == NULL) {tmp_s = malloc(sizeof(Student));if (tmp_s == NULL) {printf("malloc Student failed!\n");exit(-1);}tmp_s->next = NULL;tmp_s->id = s.id;strcpy(tmp_s->name, s.name);tmp_s->score = s.score;cur->next = tmp_s;break;}cur = cur->next;}stu_db.student_count++;printf("Student added successfully, all student: %d!\n", stu_db.student_count);write_student_info(&s);} else {printf("student has in db, do nothing!\n");}
}void print_title()
{printf("%-4s %-10s %-5s\n", "ID", "Name", "Score");
}void display_all_students()
{Student *cur;printf("-------- All students info --------\n");if (stu_db.student_count == 0) {printf("No students!\n");} else {print_title();cur = stu_db.header;while (cur) {printf("%-4d %-10s %-.2f\n", cur->id, cur->name, cur->score);cur = cur->next;}}printf("--------      End       -----------\n");
}void find_student_by_id()
{int id;printf("Enter student ID to search: ");scanf("%d", &id);Student *cur = stu_db.header;while (cur) {if (cur->id == id) {printf("%-4d %-10s %-.2f\n", cur->id, cur->name, cur->score);return;}cur = cur->next;}printf("Student with ID %d not found!\n", id);
}void find_student_by_name()
{int is_find = 0;char name[MAX_NAME_LEN];printf("Enter student name to search: ");scanf("%s", name);Student *cur = stu_db.header;while (cur) {if(strcmp(cur->name, name) == 0) {printf("%-4d %-10s %-.2f\n", cur->id, cur->name, cur->score);is_find = 1;}cur = cur->next;}if (is_find == 0) {printf("Student with name %s not found!\n", name);}
}void add_score()
{int id;float score;printf("Enter student ID: ");scanf("%d", &id);printf("Enter student score: ");scanf("%f", &score);Student *cur = stu_db.header;while (cur) {if(cur->id == id) {cur->score = score;printf("Score added successfully!\n");return;}cur = cur->next;}printf("Student with ID %d not found!\n", id);
}void display_average_score()
{float total = 0.0;Student *cur = stu_db.header;while (cur) {total += cur->score;cur = cur->next;}printf("Average score of all students: %.2f\n", total / stu_db.student_count);
}int init_student_info()
{FILE *fp = fopen(STUDENT_SYSTEM, "r");if (fp == NULL) {printf("fopen student_system failed!\n");return 1;}#define BUF_SIZE 1024char buf[BUF_SIZE];Student *s, *current;while(fgets(buf, BUF_SIZE - 1, fp) != NULL) {s = malloc(sizeof(Student));if (s == NULL) {printf("malloc Student failed!\n");exit(-1);}s->next = NULL;sscanf(buf, "%d %s %f\n", &s->id, s->name, &s->score);stu_db.student_count++;if (stu_db.header == NULL) {stu_db.header = s;current = s;} else {current->next = s;current = s;}}fclose(fp);return 0;}int main()
{int choice;int ret;ret = init_student_info();if (ret) {printf("init_student_info failed!\n");return 1;}display_all_students();do {printf("\nStudent Score Management System\n");printf("1. Add Student\n");printf("2. Display All Students\n");printf("3. Find Student by ID\n");printf("4. Find Student by Name\n");printf("5. Add Score\n");printf("6. Display Average Score\n");printf("7. Exit\n");printf("Enter your choice: ");scanf("%d", &choice);switch(choice) {case 1:add_student();break;case 2:display_all_students();break;case 3:find_student_by_id();break;case 4:find_student_by_name();break;case 5:add_score();break;case 6:display_average_score();break;case 7:printf("Exiting...\n");break;default:printf("Invalid choice!\n");}} while(choice != 7);return 0;
}

总结

通过链表重构学生成绩管理系统,学生上限数除了受限于内存,其他不受限制。链表相较于数组,它有灵活的扩展的优势,但是它的内存不是连续的,访问性能比不上数组。
虽然当前数组实现的查询,也是遍历数组,但是这里是可以进行排序优化查询的,但是链表不行。
在高性能转发场景中,比如dpdk场景中,使用的还是数组

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

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

相关文章

“分布式透明化”在杭州银行核心系统上线之思考

导读 随着金融行业数字化转型的需求&#xff0c;银行核心系统的升级改造成为重要议题。杭州银行成功上线以 TiDB 为底层数据库的新一代核心业务系统&#xff0c;该实践采用应用与基础设施解耦、分布式透明化的设计开发理念&#xff0c;推动银行核心系统的整体升级。 本文聚焦…

C语言从零实现贪吃蛇小游戏

制作不易&#xff0c;点赞关注一下呗&#xff01;&#xff01;&#xff01; 文章目录 前言一. 技术要点二、WIN32API介绍三、贪吃蛇游戏设计与分析 1.游戏开始前的初始化 2.游戏运行的逻辑 总结 前言 当我们掌握链表这样的数据结构之后&#xff0c;我们就可以用它来…

【数据结构】16 二叉树的定义,性质,存储结构(以及先序、后序、中序遍历)

二叉树 一个二叉树是一个有穷的结点集合。 它是由根节点和称为其左子树和右子树的两个不相交的二叉树组成的。 二叉树可具有以下5种形态。 性质 一个二叉树第i层的最大结点数为 2 i − 1 2^{i-1} 2i−1, i ≥ 1 i \geq 1 i≥1 每层最大结点可以对应完美二叉树&#xff08;…

Linux:docker搭建redis集群(3主3从扩容缩容 哈希槽分配)

操作系统&#xff1a;centos7 docker-ce版本&#xff1a;24.0.7 1.准备redis镜像 我这里使用redis 6.0.8 镜像进行操作&#xff0c;如果你也需要镜像&#xff0c;在网络正常情况下直接使用 docker pull redis:6.0.8 即可进行下载&#xff0c;如果你没配置国内加速器&#x…

相机图像质量研究(22)常见问题总结:CMOS期间对成像的影响--光学串扰

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…

机器人专题:我国机器人产业园区发展现状、问题、经验及建议

今天分享的是机器人系列深度研究报告&#xff1a;《机器人专题&#xff1a;我国机器人产业园区发展现状、问题、经验及建议》。 &#xff08;报告出品方&#xff1a;赛迪研究院&#xff09; 报告共计&#xff1a;26页 机器人作为推动工业化发展和数字中国建设的重要工具&…

LEETCODE 69. x 的平方根

class Solution { public:int mySqrt(int x) {int left0;int rightx;int midleft(right-left)/2;int ans-1;while(left<right){midleft(right-left)/2;if((long long)mid*mid<x){ansmid;leftmid1;}else{rightmid-1;}}return ans;} };*(long long)

js示例1(图片轮播)

<!DOCTYPE html> <html><head><meta charset"utf-8"><title>图片轮播</title><style>#box{ /*给图片盒子创建样式*/ width : 400px;height : 400px; margin: 0 auto; position: rela…

Qlik Sense : 条形图

条形图 “条形图适合比较多个值。维度轴显示所比较的类别条目&#xff0c;度量轴显示每个类别条目的值。” Qlik Sense中的条形图是一种数据可视化工具&#xff0c;用于展示不同类别或维度之间的比较。它通过水平或垂直的条形表示数据&#xff0c;并根据数值的大小进行排序。…

JavaWeb之Servlet接口

Servlet接口 什么是Servlet&#xff1f; Servlet是一种基于Java技术的Web组件&#xff0c;用于生成动态内容&#xff0c;由容器管理&#xff0c;是平台无关的Java类组成&#xff0c;并且由Java Web服务器加载执行&#xff0c;是Web容器的最基本组成单元 什么是Servlet容器&…

如何在电脑和 SD 卡上恢复已删除 MOV等视频文件

MOV 是 Apple 创建的多媒体容器。您可能已经意识到&#xff0c;用 macOS QuickTime Player 录制的视频是以 MOV 格式保存的&#xff0c;而且 MOV 在 Windows 上也兼容。我们可能已经保存了很多 MOV 格式的视频。但是&#xff0c;如果这些 MOV 文件丢失或被意外删除怎么办&#…

14-k8s控制器资源-rs控制器replicasets

replicaset副本控制器&#xff0c;简称&#xff1a;rs控制器&#xff1b; 用法&#xff1a;与rc控制器“几乎”相同&#xff1b; 能力&#xff1a;可以指定pod的副本始终存活&#xff0c;相比于rc控制器&#xff1b;支持标签匹配&#xff0c;也支持标签表达式 注意&#xff1a;…