嗨~~欢迎来到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不断前行的源泉✨!衷心感谢你的鼓励与陪伴🙏!
若你有任何疑问、见解或补充,欢迎随时留言💬,让我们在交流中共同成长📚!❤️
愿各位大佬们在技术的道路上,代码顺畅无阻💻,思路清晰如光💡,不断突破自我,向着更高的目标迈进,实现自己的梦想!🎉
再次感谢你的阅读🌸