要求:完成学生管理的链表程序。具有学生信息增加、显示、修改、删除、查找、学生人数统计功能的程序。增加学生信息时,按照学号排序;根据给定的学号,可以完成指定学号的修改、删除和查找功能。
目录
一.定义数据结构
1)定义学生结构体的数据结构
typedef struct Student{
char studentName[NAME_LENGTH];//姓名
char studentNo[NO_LENGTH];//学号
char studentgender[GENDER_LENGTH];//性别
char studentleague[LEAGUE_LENGTH];//政治面貌
}st;
2)定义每条记录或节点的数据结构
typedef struct node{
struct Student data;//数据域,是Student结构类型的
struct node*next;//指针域,指向node类型的结构
}Node,*Link;
二.主函数
1)创建头指针
2)输入选择的程序功能
int main(){
Link head;
int select;
head=(Link)malloc(sizef(Node));
head->next=NULL;
while(1){//除非手动选择退出循环,否则一直继续
myMenu();
printf("请输入你的选择(1~7)");
scanf("%d",&select);
switch(select){
case 1://增加学生记录
if (addNode(head))
printf("成功插入一个学生记录。\n\n");
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);
break;
case 7:clearLink(head);
return 0;
default: printf("输入不正确,应该输入0-7之间的数。\n\n");
break;
}
}
return 0;
}
三.执行功能的函数
所有函数中要比较两个字符串是否相同,要调用strcmp函数,不能直接用==比较
替换调用strcpy函数
1)每次操作均会打印,请求输入学号的函数
void inputStudentNo(char s[], char no[]) {
printf("请输入要%s的学生学号:", s);
scanf("%s", no);
}
(这里专门编写这个函数可以简化后续的代码)
2)增加学生记录
bool addNode(Link head){
Link node;
node=(Link)malloc(sizeof(Node));
inputStudent(node);//给数据域填信息
Link p,q;//用来查找插入数据点
p=head;
q=head->next;
if(q==NULL)//如果还没有添加数据
head->next=node;
else{
//循环访问链表中的所有节点
while(q!=NULL){
if (strcmp(node->data.studentNo, q->data.studentNo) < 0) {
p->next=node;
node->next=q;
return true;
}else{
p=q;
q=q->next;
}
}
//如果没能提前退出循环,则说明之前没有插入,那么当前node节点的学号是最大值,此时插在链表的最后面
q->next=node;
}
return true;
}
(这个是给每个链表数据域填信息的函数,重点是将每个结点的next域都先赋为NULL )
void inputStudent(Link l) {
printf("请输入学生学号:");
scanf("%s", l->data.studentNo);
printf("请输入学生的姓名:");
scanf("%s", l->data.studentName);
printf("请输入学生的性别:");
scanf("%s", l->data.studentgender);
printf("请输入学生的政治面貌:");
scanf("%s", l->data.studentleague);
//每个新创建的节点的next域都初始化为NULL
l->next = NULL;
}
3)删除学生记录
bool deleteNode(Link head) {
// 按照给定的学号删除学生记录,如果删除成功返回true,如果没找到学号返回false
//输入要处理的学号
char no[NO_LENGTH];
inputStudentNo("删除", no);
if (head == NULL || head->next == NULL)
return false;
Link p, q;
p = head;
q = head->next;
while (q != NULL) {
if (strcmp(q->data.studentNo, no) == 0) {
p->next = q->next;
free(q);
return true;
} else {
p = q;
q = q->next;
}
}
return false;
}
3)查找学生记录
bool queryNode(Link head) {
// 按照给定的学号查询学生记录,如果查找成功返回true,如果没找到学号返回false
//输入要处理的学号
char no[NO_LENGTH];
inputStudentNo("查询", no);
if (head == NULL || head->next == NULL)
return false;
Link p;
p = head->next;
while (p != NULL) {
if (strcmp(p->data.studentNo, no) == 0)
return true;
else
p = p->next;
}
return false;
}
4)修改学生记录
bool modifyNode(Link head) {
// 按照给定的学号找到学生记录节点,如果修改成功返回true,如果没找到学号返回false
//输入要处理的学号
char no[NO_LENGTH];
inputStudentNo("修改", no);
if (head == NULL || head->next == NULL)
return false;
char resetno[NO_LENGTH];
char resetname[NAME_LENGTH];
char resetgender[GENDER_LENGTH];
char resetleague[LEAGUE_LENGTH];
Link p = head->next;
while (p != NULL) {
if (strcmp(p->data.studentNo, no) == 0) {
printf("请输入您要修改的信息类型:\n");
char type[20];
scanf("%s", type);
if (strcmp(type, "姓名") == 0) {
printf("请输入修改后的姓名:\n");
scanf("%s", resetname);
strcpy(p->data.studentName, resetname);
return true;
} else if (strcmp(type, "学号") == 0) {
printf("请输入修改后的学号:\n");
scanf("%s", resetno);
strcpy(p->data.studentNo, resetno);
return true;
}
else if (strcmp(type, "性别") == 0) {
printf("请输入修改后的性别:\n");
scanf("%s", resetgender);
strcpy(p->data.studentgender, resetgender);
return true;
}
else if (strcmp(type, "政治面貌") == 0) {
printf("请输入修改后的政治面貌:\n");
scanf("%s", resetleague);
strcpy(p->data.studentleague, resetleague);
return true;
}
} else {
p = p->next;
}
}
return false;
}
5)统计学生人数
int countNode(Link head) {
//统计学生人数,扫描链表统计节点个数,返回节点数
Link p;
int count = 0;
p = head->next;
while (p != NULL) {
count++;
p = p->next;
}
return count;
//填充代码
}
6)显示学生信息
void displayNode(Link head) {
// 填写代码,根据传入的链表head头指针,扫描链表显示所有节点的信息
Link p = head->next;
while (p != NULL) {
printf("%s %s %s %s\n", p->data.studentName, p->data.studentNo,p->data.studentgender,p->data.studentleague);
p = p->next;
}
}
7)退出系统
void clearLink(Link head) {
Link q, p;
//遍历链表,用free语句删除链表中用malloc建立起的所有的节点
while (head->next != NULL) {
p = head;
head = head->next;
free(p);
}
}
四,完整代码
这里参考了《懒猫老师-C语言-链表作业1:学生管理系统》实验的题目模板~有错误欢迎指正呀~
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>
#include <stdbool.h>
#define NO_LENGTH 20
#define NAME_LENGTH 11
#define GENDER_LENGTH 11
#define LEAGUE_LENGTH 11
/* 定义学生结构体的数据结构 */
typedef struct Student {
char studentName[NAME_LENGTH];//姓名
char studentNo[NO_LENGTH];//学号
char studentgender[GENDER_LENGTH];//性别
char studentleague[LEAGUE_LENGTH];//政治面貌
} st;
/* 定义每条记录或节点的数据结构 */
typedef struct node {
struct Student data; //数据域
struct node *next; //指针域
} Node, *Link; //Node为node类型的别名,Link为node类型的指针别名
//定义提示菜单
void myMenu() {
printf(" * * * * * * * * * 菜 单 * * * * * * * * * *\n");
printf(" 1 增加学生记录 2 删除学生记录 \n");
printf(" 3 查找学生记录 4 修改学生记录 \n");
printf(" 5 统计学生人数 6 显示学生记录 \n");
printf(" 7 退出系统 \n");
printf(" * * * * * * * * * * * * * * * * * * * * * * * *\n");
}
void inputStudent(Link l) {
printf("请输入学生学号:");
scanf("%s", l->data.studentNo);
printf("请输入学生的姓名:");
scanf("%s", l->data.studentName);
printf("请输入学生的性别:");
scanf("%s", l->data.studentgender);
printf("请输入学生的政治面貌:");
scanf("%s", l->data.studentleague);
//每个新创建的节点的next域都初始化为NULL
l->next = NULL;
}
void inputStudentNo(char s[], char no[]) {
printf("请输入要%s的学生学号:", s);
scanf("%s", no);
}
void displayNode(Link head) {
// 填写代码,根据传入的链表head头指针,扫描链表显示所有节点的信息
Link p = head->next;
while (p != NULL) {
printf("%s %s %s %s\n", p->data.studentName, p->data.studentNo, p->data.studentgender, p->data.studentleague);
p = p->next;
}
}
/* 增加学生记录 */
bool addNode(Link head) {
Link p, q; //p,q两个节点一前一后
Link node; //node指针指向新创建的节点
node = (Link)malloc(sizeof(Node));
inputStudent(node);
q = head;
p = head->next; //q指向head后面的第一个有效节点
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节点的学号大,继续向后移动指针(依然保持pq一前一后)
q = p;
p = p->next;
}
}
//如果没能提前退出循环,则说明之前没有插入,那么当前node节点的学号是最大值,此时插在链表的最后面
q->next = node;
}
return true;
}
bool deleteNode(Link head) {
// 按照给定的学号删除学生记录,如果删除成功返回true,如果没找到学号返回false
//输入要处理的学号
char no[NO_LENGTH];
inputStudentNo("删除", no);
if (head == NULL || head->next == NULL)
return false;
Link p, q;
p = head;
q = head->next;
while (q != NULL) {
if (strcmp(q->data.studentNo, no) == 0) {
p->next = q->next;
free(q);
return true;
} else {
p = q;
q = q->next;
}
}
return false;
}
bool queryNode(Link head) {
// 按照给定的学号查询学生记录,如果查找成功返回true,如果没找到学号返回false
//输入要处理的学号
char no[NO_LENGTH];
inputStudentNo("查询", no);
if (head == NULL || head->next == NULL)
return false;
Link p;
p = head->next;
while (p != NULL) {
if (strcmp(p->data.studentNo, no) == 0)
return true;
else
p = p->next;
}
return false;
}
bool modifyNode(Link head) {
// 按照给定的学号找到学生记录节点,如果修改成功返回true,如果没找到学号返回false
//输入要处理的学号
char no[NO_LENGTH];
inputStudentNo("修改", no);
if (head == NULL || head->next == NULL)
return false;
char resetno[NO_LENGTH];
char resetname[NAME_LENGTH];
char resetgender[GENDER_LENGTH];
char resetleague[LEAGUE_LENGTH];
Link p = head->next;
while (p != NULL) {
if (strcmp(p->data.studentNo, no) == 0) {
printf("请输入您要修改的信息类型:\n");
char type[20];
scanf("%s", type);
if (strcmp(type, "姓名") == 0) {
printf("请输入修改后的姓名:\n");
scanf("%s", resetname);
strcpy(p->data.studentName, resetname);
return true;
} else if (strcmp(type, "学号") == 0) {
printf("请输入修改后的学号:\n");
scanf("%s", resetno);
strcpy(p->data.studentNo, resetno);
return true;
} else if (strcmp(type, "性别") == 0) {
printf("请输入修改后的性别:\n");
scanf("%s", resetgender);
strcpy(p->data.studentgender, resetgender);
return true;
} else if (strcmp(type, "政治面貌") == 0) {
printf("请输入修改后的政治面貌:\n");
scanf("%s", resetleague);
strcpy(p->data.studentleague, resetleague);
return true;
}
} else {
p = p->next;
}
}
return false;
}
int countNode(Link head) {
//统计学生人数,扫描链表统计节点个数,返回节点数
Link p;
int count = 0;
p = head->next;
while (p != NULL) {
count++;
p = p->next;
}
return count;
//填充代码
}
void clearLink(Link head) {
Link q, p;
//遍历链表,用free语句删除链表中用malloc建立起的所有的节点
while (head->next != NULL) {
p = head;
head = head->next;
free(p);
}
}
int main() {
int select;
int count;
Link head; // 定义链表
//建立head头结点,在这个程序中head指向头结点,头结点data部分没有内容,其后续节点才有真正的数据
head = (Link)malloc(sizeof(Node));
head->next = NULL;
while (1) {
myMenu();
printf("\n请输入你的选择(0-7):"); //显示提示信息
scanf("%d", &select);
switch (select) {
case 1:
//增加学生记录
if (addNode(head))
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);
break;
case 7:
//退出前清除链表中的所有结点
clearLink(head);
return 0;
default:
printf("输入不正确,应该输入0-7之间的数。\n\n");
break;
}
}
return 0;
}