【实现报告】学生信息管理系统(链表实现)

news2024/11/29 6:38:55

目录

实验一 线性表的基本操作

一、实验目的

二、实验内容

三、实验提示

四、实验要求

五、实验代码如下:

(一)链表的构建及初始化

学生信息结构体定义

定义元素类型

链表节点结构体定义

初始化链表

(二)创建一个新节点

(三)根据指定学生个数,逐个输入学生信息

函数参数

查找第i-1个节点

检查插入位置的合法性

创建新节点并插入链表

(四)逐个显示学生表中所有学生的相关信息

(五)根据姓名进行查找,返回此学生的学号和成绩

(六)根据指定的位置可返回相应的学生信息(学号,姓名,成绩);

(七) 给定一个学生信息,插入到表中指定的位置

 (八)删除指定位置的学生记录

 (九)退出程序,释放链表

(十)main函数

运行截图:

六、整体代码如下: 


实验一 线性表的基本操作

一、实验目的

1、掌握线性表的定义;

2、掌握线性表的基本操作,如建立、查找、插入和删除等。

二、实验内容

定义一个包含学生信息(学号,姓名,成绩)的顺序表和链表,使其具有如下功能:

(1) 根据指定学生个数,逐个输入学生信息;

(2) 逐个显示学生表中所有学生的相关信息;

(3) 根据姓名进行查找,返回此学生的学号和成绩;

(4) 根据指定的位置可返回相应的学生信息(学号,姓名,成绩);

(5) 给定一个学生信息,插入到表中指定的位置;

(6) 删除指定位置的学生记录;

(7) 统计表中学生个数。

三、实验提示

学生信息的定义:

typedef struct {

    char no[8];   //8位学号

    char name[20]; //姓名

    int grade;     //成绩

}Student;

顺序表的定义

typedef  struct {

  Student  *elem;     //指向数据元素的基地址

  int  length;       //线性表的当前长度                                                           

 }SqList;

链表的定义:

typedef struct LNode{

     Student   data;       //数据域

     struct LNode  *next;   //指针域

}LNode,*LinkList;

四、实验要求

(1) 程序要添加适当的注释,程序的书写要采用缩进格式。

(2) 程序要具有一定的健壮性,即当输入数据非法时,程序也能适当地做出反应,如插入删除时指定的位置不对等等。

(3) 程序要做到界面友好,在程序运行时用户可以根据相应的提示信息进行操作。

(4) 根据实验报告模板详细书写实验报告,在实验报告中给出链表根据姓名进行查找的算法和插入算法的流程图。

五、实验代码如下:

(一)链表的构建及初始化

学生信息结构体定义

  • typedef struct定义了一个名为student的结构体,用于存储单个学生的信息。
    • char no[8];:存储8位学号。
    • char name[20];:存储学生姓名,最多19个字符加上一个字符串结束符\0
    • double score;:存储学生的成绩,类型为double以支持小数。

定义元素类型

  • typedef student ElemType;:定义了一个新的类型名ElemType,其实就是student结构体。这样做可以增加代码的可读性和可维护性,也方便以后对元素类型的修改。

链表节点结构体定义

  • typedef struct LNode定义了链表节点的结构体,每个节点包括:
    • ElemType data;:数据域,用于存储一个ElemType类型的数据,在这里即为student结构体实例。
    • struct LNode* next;:指针域,用于指向链表中下一个节点的地址。如果这是链表的最后一个节点,则nextNULL

初始化链表

  • bool InitList(LN* L)函数用于初始化一个链表。
    • 首先,使用malloc分配一个LNode类型节点的内存空间给链表的头节点。头节点通常不存储有效数据,它的作用是作为链表的入口点。
    • 如果内存分配失败(即malloc返回NULL),则输出错误信息并返回false
    • 成功分配内存后,将头节点的next指针设置为NULL,表示链表为空。
    • 返回true表示链表初始化成功。
// 学生信息结构体定义
typedef struct {
    char no[8];   // 8位学号
    char name[20]; // 姓名
    double score;  // 成绩
} student;

// 定义元素类型
typedef student ElemType;

// 链表节点结构体定义
typedef struct LNode {
    ElemType data;       // 数据域,存储学生信息
    struct LNode* next;  // 指针域,指向下一个节点
} LNode, *LN;

// 初始化链表
bool InitList(LN* L) {
    *L = (LNode*)malloc(sizeof(LNode)); // 分配头节点空间
    if (!(*L)) { // 内存分配失败的处理
        printf("malloc fail");
        return false;
    }
    (*L)->next = NULL; // 头节点的指针域设置为空
    return true;
}

(二)创建一个新节点

  • LN BuySListNode(ElemType x)函数用于创建一个新的链表节点,并存储提供的学生信息x
    • 与初始化链表类似,先使用malloc为新节点分配内存空间。
    • 如果内存分配失败,则输出错误信息并通过exit(-1);退出程序。这是一种极端的错误处理方式,实际应用中可能会选择更温和的错误处理策略。
    • 成功分配内存后,将传入的学生信息x赋值给新节点的数据域,同时设置新节点的指针域为NULL
    • 返回新创建的节点。
// 创建一个新节点,存储学生信息
LN BuySListNode(ElemType x) {
    LN newnode = (LN)malloc(sizeof(LNode)); // 为新节点分配空间
    if (!newnode) { // 内存分配失败的处理
        printf("malloc fail");
        exit(-1);
    }
    newnode->data = x; // 设置数据域
    newnode->next = NULL; // 新节点的指针域设置为空
    return newnode;
}

(三)根据指定学生个数,逐个输入学生信息

函数参数

  • LN L:指向链表头节点的指针。
  • int i:指定的插入位置,位置编号从1开始。
  • ElemType e:要插入的学生信息,ElemType是学生信息结构体student的别名。

查找第i-1个节点

  • 从链表的头节点开始遍历,目标是找到第i-1个节点。这是因为在单链表中插入一个新节点时,需要修改第i-1个节点的next指针,使其指向新插入的节点。
  • LN p = L;初始化遍历指针p为链表的头节点。
  • int j = 0;初始化计数器j,用来记录当前遍历到链表的第几个节点。
  • 使用while循环移动p,直到p指向第i-1个节点或链表结束。循环条件p && j < i - 1确保只有当p非空且j小于i-1时循环继续。

检查插入位置的合法性

  • 在尝试插入新节点前,需要确认找到的位置是合法的。
  • if (!p || j > i - 1) return false;如果p为空,或j大于i-1,说明指定的插入位置i无效(例如,超出了链表长度)。此时函数返回false,表示插入操作失败。

创建新节点并插入链表

  • LN s = BuySListNode(e);创建一个新的链表节点s,并将要插入的学生信息e存储于此节点。BuySListNode函数负责分配内存,并初始化新节点的数据和指针域。
  • s->next = p->next;将新节点snext指针设置为pnext指针当前指向的节点,即将s链接到链表中的正确位置。
  • p->next = s;更新第i-1个节点的next指针,使其指向新插入的节点s。这样,节点s就被正确插入到链表的第i个位置。
  • 返回true表示插入操作成功。

// 输入学生信息
void Input(ElemType* e) {
    printf("学号: "); scanf("%s", e->no);
    printf("姓名: "); scanf("%s", e->name);
    printf("成绩: "); scanf("%lf", &e->score);
    printf("输入完成\n\n");
}

// 在链表的指定位置插入学生信息
bool ListInsert(LN L, int i, ElemType e) {
    LN p = L;
    int j = 0;
    // 查找第i-1个节点
    while (p && j < i - 1) {
        p = p->next;
        ++j;
    }
    // 插入位置不合法的处理
    if (!p || j > i - 1) return false;
    // 创建新节点并插入链表
    LN s = BuySListNode(e);
    s->next = p->next;
    p->next = s;
    return true;
}

// 输入学生信息
printf("请输入要录入的学生人数:");
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
     printf("第%d个学生:\n", i);
     ElemType* a = (ElemType*)malloc(sizeof(ElemType)); // 动态分配每个学生的空间
     if (a == NULL) {
           printf("内存分配失败\n");
           exit(-1);
        }
          Input(a); // 修改Input函数以接受ElemType指针
          ListInsert(L, i, *a); // 插入链表
 }

(四)逐个显示学生表中所有学生的相关信息

// 输出学生信息
void Output(ElemType e) {
    printf("学号:%-10s\n姓名:%-20s\n成绩:%-10.2lf\n\n", e.no, e.name, e.score);
}

// 获取链表中指定位置的学生信息
void GetElem(LN L, int i, ElemType* e) {
    LN p = L->next; // 从头节点的下一个节点开始
    int j = 1;
    // 查找第i个节点
    while (p && j < i) {
        p = p->next;
        ++j;
    }
    // 若位置i不合法,则直接返回
    if (!p || j > i) return;
    *e = p->data; // 将找到的节点的数据复制到e指向的变量中
}

for (i = 1; i <= n; ++i) {
    GetElem(L, i, &b);
    Output(b);
}

(五)根据姓名进行查找,返回此学生的学号和成绩

// 根据姓名查找学生信息
bool Search(LN L, char str[], LN* p) {
    *p = L->next; // 从头节点的下一个节点开始查找
    while (*p) {
        // 比较当前节点学生姓名是否与给定姓名相同
        if (!strcmp((*p)->data.name, str))
            return true;
        *p = (*p)->next;
    }
    return false; // 未找到指定姓名的学生
}

// 根据姓名查找学生
printf("请输入要查找的学生姓名: ");
scanf("%s", str);
if (Search(L, str, &t)) {
    Output(t->data);
}
else {
    printf("没有此学生的信息!\n");
}

(六)根据指定的位置可返回相应的学生信息(学号,姓名,成绩);

  1. 设置起始节点

    LN p = L->next:定义并初始化一个指针变量p,用于遍历链表。它被设置为指向链表的第一个元素节点(头节点的下一个节点)。
  2. 初始化计数器

    int j = 1;定义并初始化计数器j为1,用于追踪当前遍历到的节点位置。
  3. 遍历链表定位元素

    • 使用while循环遍历链表,直到找到第i个节点或到达链表末尾(p变为NULL)。
    • 循环条件p && j < i确保了只有当当前节点p非空且计数器j小于目标位置i时,循环才会继续。在每次循环中,p会更新为下一个节点(p = p->next;),同时计数器j增加1(++j;)。
  4. 检查位置合法性

    在循环结束后,通过检查if (!p || j > i)来确定是否成功找到了第i个节点。如果pNULLj大于i,意味着目标位置i超出了链表的长度,此时函数直接返回,不进行任何操作。
  5. 复制节点数据

    如果成功找到了第i个节点(即p非空且j等于i),则将该节点的数据(p->data)复制到通过参数e传入的变量中(*e = p->data;)。
// 获取链表中指定位置的学生信息
void GetElem(LN L, int i, ElemType* e) {
    LN p = L->next; // 从头节点的下一个节点开始
    int j = 1;
    // 查找第i个节点
    while (p && j < i) {
        p = p->next;
        ++j;
    }
    // 若位置i不合法,则直接返回
    if (!p || j > i) return;
    *e = p->data; // 将找到的节点的数据复制到e指向的变量中
}

// 显示指定位置的学生信息
printf("请输入要查询的位置:");
scanf("%d", &d1);
GetElem(L, d1, &c);
Output(c);

(七) 给定一个学生信息,插入到表中指定的位置

  1. 查找第i-1个节点

    • 函数开始时,首先设置一个指针p来遍历链表,从链表的头节点L开始。同时,设置一个计数器j来记录当前遍历到的位置,初始化为0。
    • 使用while循环,条件是p非空并且j < i - 1,即尝试移动p直到它指向第i-1个节点。这是因为在链表中插入一个新节点,需要修改前一个节点的next指针。
    • 每次循环中,p移动到下一个节点(p = p->next),并且计数器j递增。
  2. 检查插入位置的合法性

    • 循环结束后,使用if (!p || j > i - 1)来检查是否成功找到了有效的插入位置。如果p为空(即到达了链表末尾之后)或者j超过了i-1(这通常不会发生,因为循环条件限制了j < i - 1),则认为插入位置不合法,函数返回false
  3. 创建新节点并插入链表

    • 通过调用BuySListNode(e)创建一个新的链表节点s,并将要插入的学生信息e填充到该节点的数据域中。这个函数负责分配内存并初始化节点。
    • 将新节点snext指针设置为p的下一个节点,即p->next,这样新节点s就链接到了链表中的正确位置。
    • 更新pnext指针,使其指向新节点s,从而将s正式插入到链表中。
    • 最后,函数返回true,表示插入操作成功。
// 在链表的指定位置插入学生信息
bool ListInsert(LN L, int i, ElemType e) {
    LN p = L;
    int j = 0;
    // 查找第i-1个节点
    while (p && j < i - 1) {
        p = p->next;
        ++j;
    }
    // 插入位置不合法的处理
    if (!p || j > i - 1) return false;
    // 创建新节点并插入链表
    LN s = BuySListNode(e);
    s->next = p->next;
    p->next = s;
    return true;
}

//给定一个学生信息,插入到表中指定的位置;
printf("请输入要插入的位置:");
scanf("%d", &id2);
printf("输入要插入的人数:");
scanf("%d", &n);
for (i = 1; i <= n; i++)
{
	printf("请输入第 %d 个学生:\n", i);
	Input(&a);
	if (ListInsert(ps, id2, &a))
	{
		puts("插入成功");
	}
	else
	{
		puts("插入失败\n");
	}
}

 (八)删除指定位置的学生记录

  • 初始化指针和计数器

    • LN p = L;:定义并初始化一个指针变量p,用于遍历链表,初始指向链表的头节点。
    • LN q;:定义一个指针变量q,用于临时存储待删除节点的地址。
    • int j = 0;:定义并初始化计数器j为0,用于记录当前p指针所在的节点位置。
  • 查找第i-1个节点

    • 使用while循环移动p指针,目的是定位到第i-1个节点。这是因为在单链表中删除一个节点时,需要修改其前驱节点的next指针。
    • 循环条件p->next && j < i - 1确保了只有当p的下一个节点存在(即p不是尾节点)且j小于目标位置i减1时,循环才会继续。这样,当循环结束时,p应该指向第i-1个节点。
  • 检查删除位置的合法性

    • if (!(p->next) || j > i - 1):这个条件检查是否存在第i个节点。如果p的下一个节点不存在(即p已经是尾节点了)或者计数器j大于i-1(理论上不会发生,因为循环条件已经限制了j < i - 1),则表示要删除的位置i是不合法的(超出了链表的长度或者是非正数),函数返回false
  • 删除节点

    • q = p->next;:将q指向要删除的节点,即第i个节点,也就是p的下一个节点。
    • p->next = q->next;:将pnext指针指向q的下一个节点,从而在链表中跳过q节点,实现删除操作。
    • free(q);:释放q节点占用的内存空间。free是C语言标准库函数,用于释放之前通过malloccallocrealloc函数分配的内存。
  • 返回删除成功的标志

    • 函数最后返回true,表示节点删除成功。

// 删除链表中指定位置的学生记录
bool ListDelete(LN L, int i) {
    LN p = L, q;
    int j = 0;
    // 查找第i-1个节点
    while (p->next && j < i - 1) {
        p = p->next;
        ++j;
    }
    // 删除位置不合法的处理
    if (!(p->next) || j > i - 1) return false;
    q = p->next; // q指向要删除的节点
    p->next = q->next; // 删除节点q
    free(q); // 释放节点q的内存空间
    return true;
}

 (九)退出程序,释放链表

  1. 定义变量

    • LN current = *L;:定义一个指针变量current用于遍历链表,它被初始化为指向链表的头节点。
    • LN next;:定义一个指针变量next,用于临时存储当前节点的下一个节点的地址,以便在释放当前节点内存后仍能继续遍历链表。
  2. 遍历链表

    使用while循环遍历链表,循环条件current != NULL确保只要当前节点非空,循环就继续。
  3. 保存下一个节点的地址

    在释放当前节点内存之前,需要先保存下一个节点的地址,因为一旦当前节点被释放,就无法通过当前节点的next指针访问下一个节点了。
  4. 释放当前节点

    使用free(current);释放当前节点占用的内存。free函数是C语言标准库中的函数,用于释放之前通过malloccallocrealloc函数分配的内存。
  5. 移动到下一个节点:将current更新为next,即移动到链表的下一个节点,为下一次循环的执行做准备。这一步是在current = next;这行代码中完成的。

  6. 将链表头指针设置为NULL

  • 在链表的所有节点都被释放后,最后一步是将链表的头指针设置为NULL,表示链表为空。这是通过*L = NULL;这行代码完成的。
// 释放链表占用的内存
void FreeList(LN* L) {
    LN current = *L; // current用于遍历链表
    LN next;

    while (current != NULL) {
        next = current->next; // 保存下一个节点的指针
        free(current); // 释放当前节点
        current = next; // 移动到下一个节点
    }

    *L = NULL; // 最后将链表头指针设置为NULL
}

if (choose == 9)
{
    break; // 选择9则退出程序
    // 用户选择退出程序前释放链表
    FreeList(&L);
}

(十)main函数

int main() {
    LN L, t = NULL; // L是链表头指针,t用于临时存储查找到的节点
    ElemType a, b, c; // 用于临时存储和操作学生信息

    printf("\n1.构造链表\n");
    printf("2.输入学生信息\n");
    printf("3.显示学生表信息\n");
    printf("4.根据姓名进行查找\n");
    printf("5.显示指定的位置学生信息\n");
    printf("6.在指定位置插入学生信息\n");
    printf("7.删除指定位置的学生记录\n");
    printf("8.统计学生人数\n");
    printf("9.退出\n\n");

    int n = 0, choose = 0, i = 0, d1 = 0; // n用于记录学生总数,choose用于用户选择,d1用于临时存放用户输入的位置
    char str[20]; // 用于存放用户查找时输入的姓名
    while (1) {
        printf("请选择:");
        scanf("%d", &choose);
        if (choose == 9)
        {
            break; // 选择9则退出程序
            // 用户选择退出程序前释放链表
            FreeList(&L);
        }
        switch (choose) {
        case 1: 
            // 初始化链表
            if (!InitList(&L)) {
                printf("链表初始化失败。\n");
                return 1;
            }
            else
            printf("链表已初始化。\n");
            break;
        Case 2: // 输入学生信息
            printf("请输入要录入的学生人数:");
            scanf("%d", &n);
            for (int i = 1; i <= n; i++) {
                printf("第%d个学生:\n", i);
                ElemType* a = (ElemType*)malloc(sizeof(ElemType)); // 动态分配每个学生的空间
                if (a == NULL) {
                    printf("内存分配失败\n");
                    exit(-1);
                }
                Input(a); // 修改Input函数以接受ElemType指针
                ListInsert(L, i, *a); // 插入链表
            }
        Case 3: // 显示所有学生信息
            for (i = 1; i <= n; ++i) {
                GetElem(L, i, &b);
                Output(b);
            }
        
        Case 4: // 根据姓名查找学生
            printf("请输入要查找的学生姓名: ");
            scanf("%s", str);
            if (Search(L, str, &t)) {
                Output(t->data);
            }
            else {
                printf("没有此学生的信息!\n");
            }
        Case 5: // 显示指定位置的学生信息
            printf("请输入要查询的位置:");
            scanf("%d", &d1);
            GetElem(L, d1, &c);
            Output(c);
        Case 6: // 在指定位置插入学生信息
            printf("请输入要插入的位置:");
            scanf("%d", &d1);
            printf("请输入学生信息:\n");
            Input(&c);
            if (ListInsert(L, d1, c)) {
                ++n;
                printf("插入成功\n");
            }
            else {
                printf("插入失败\n");
            }
        Case 7: // 删除指定位置的学生记录
            printf("请输入要删除的位置:");
            scanf("%d", &d1);
            if (ListDelete(L, d1)) {
                --n;
                printf("删除成功\n");
            }
            else {
                printf("删除失败\n");
            }
        Case 8: // 统计学生人数
            printf("已录入的学生个数为:%d\n\n", n);
            break;
        default:
            printf("无效选项\n");
        }
    }

    return 0;
}

运行截图:

六、整体代码如下: 

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
#define Case break;case

// 学生信息结构体定义
typedef struct {
    char no[8];   // 8位学号
    char name[20]; // 姓名
    double score;  // 成绩
} student;

// 定义元素类型
typedef student ElemType;

// 链表节点结构体定义
typedef struct LNode {
    ElemType data;       // 数据域,存储学生信息
    struct LNode* next;  // 指针域,指向下一个节点
} LNode, *LN;

// 初始化链表
bool InitList(LN* L) {
    *L = (LNode*)malloc(sizeof(LNode)); // 分配头节点空间
    if (!(*L)) { // 内存分配失败的处理
        printf("malloc fail");
        return false;
    }
    (*L)->next = NULL; // 头节点的指针域设置为空
    return true;
}

// 创建一个新节点,存储学生信息
LN BuySListNode(ElemType x) {
    LN newnode = (LN)malloc(sizeof(LNode)); // 为新节点分配空间
    if (!newnode) { // 内存分配失败的处理
        printf("malloc fail");
        exit(-1);
    }
    newnode->data = x; // 设置数据域
    newnode->next = NULL; // 新节点的指针域设置为空
    return newnode;
}

// 在链表的指定位置插入学生信息
bool ListInsert(LN L, int i, ElemType e) {
    LN p = L;
    int j = 0;
    // 查找第i-1个节点
    while (p && j < i - 1) {
        p = p->next;
        ++j;
    }
    // 插入位置不合法的处理
    if (!p || j > i - 1) return false;
    // 创建新节点并插入链表
    LN s = BuySListNode(e);
    s->next = p->next;
    p->next = s;
    return true;
}

// 输入学生信息
void Input(ElemType* e) {
    printf("学号: "); scanf("%s", e->no);
    printf("姓名: "); scanf("%s", e->name);
    printf("成绩: "); scanf("%lf", &e->score);
    printf("输入完成\n\n");
}

// 输出学生信息
void Output(ElemType e) {
    printf("学号:%-10s\n姓名:%-20s\n成绩:%-10.2lf\n\n", e.no, e.name, e.score);
}

// 根据姓名查找学生信息
bool Search(LN L, char str[], LN* p) {
    *p = L->next; // 从头节点的下一个节点开始查找
    while (*p) {
        // 比较当前节点学生姓名是否与给定姓名相同
        if (!strcmp((*p)->data.name, str))
            return true;
        *p = (*p)->next;
    }
    return false; // 未找到指定姓名的学生
}

// 删除链表中指定位置的学生记录
bool ListDelete(LN L, int i) {
    LN p = L, q;
    int j = 0;
    // 查找第i-1个节点
    while (p->next && j < i - 1) {
        p = p->next;
        ++j;
    }
    // 删除位置不合法的处理
    if (!(p->next) || j > i - 1) return false;
    q = p->next; // q指向要删除的节点
    p->next = q->next; // 删除节点q
    free(q); // 释放节点q的内存空间
    return true;
}

// 获取链表中指定位置的学生信息
void GetElem(LN L, int i, ElemType* e) {
    LN p = L->next; // 从头节点的下一个节点开始
    int j = 1;
    // 查找第i个节点
    while (p && j < i) {
        p = p->next;
        ++j;
    }
    // 若位置i不合法,则直接返回
    if (!p || j > i) return;
    *e = p->data; // 将找到的节点的数据复制到e指向的变量中
}


// 释放链表占用的内存
void FreeList(LN* L) {
    LN current = *L; // current用于遍历链表
    LN next;

    while (current != NULL) {
        next = current->next; // 保存下一个节点的指针
        free(current); // 释放当前节点
        current = next; // 移动到下一个节点
    }

    *L = NULL; // 最后将链表头指针设置为NULL
}

int main() {
    LN L, t = NULL; // L是链表头指针,t用于临时存储查找到的节点
    ElemType a, b, c; // 用于临时存储和操作学生信息

    printf("\n1.构造链表\n");
    printf("2.输入学生信息\n");
    printf("3.显示学生表信息\n");
    printf("4.根据姓名进行查找\n");
    printf("5.显示指定的位置学生信息\n");
    printf("6.在指定位置插入学生信息\n");
    printf("7.删除指定位置的学生记录\n");
    printf("8.统计学生人数\n");
    printf("9.退出\n\n");

    int n = 0, choose = 0, i = 0, d1 = 0; 
    // n用于记录学生总数,choose用于用户选择,d1用于临时存放用户输入的位置
    char str[20]; // 用于存放用户查找时输入的姓名
    while (1) {
        printf("请选择:");
        scanf("%d", &choose);
        if (choose == 9)
        {
            break; // 选择9则退出程序
            // 用户选择退出程序前释放链表
            FreeList(&L);
        }
        switch (choose) {
        case 1: 
            // 初始化链表
            if (!InitList(&L)) {
                printf("链表初始化失败。\n");
                return 1;
            }
            else
            printf("链表已初始化。\n");
            break;
        Case 2: // 输入学生信息
            printf("请输入要录入的学生人数:");
            scanf("%d", &n);
            for (int i = 1; i <= n; i++) {
                printf("第%d个学生:\n", i);
                ElemType* a = (ElemType*)malloc(sizeof(ElemType));
                // 动态分配每个学生的空间
                if (a == NULL) {
                    printf("内存分配失败\n");
                    exit(-1);
                }
                Input(a); // 修改Input函数以接受ElemType指针
                ListInsert(L, i, *a); // 插入链表
            }
        Case 3: // 显示所有学生信息
            for (i = 1; i <= n; ++i) {
                GetElem(L, i, &b);
                Output(b);
            }
        
        Case 4: // 根据姓名查找学生
            printf("请输入要查找的学生姓名: ");
            scanf("%s", str);
            if (Search(L, str, &t)) {
                Output(t->data);
            }
            else {
                printf("没有此学生的信息!\n");
            }
        Case 5: // 显示指定位置的学生信息
            printf("请输入要查询的位置:");
            scanf("%d", &d1);
            GetElem(L, d1, &c);
            Output(c);
        Case 6: // 在指定位置插入学生信息
            printf("请输入要插入的位置:");
            scanf("%d", &d1);
            printf("请输入学生信息:\n");
            Input(&c);
            if (ListInsert(L, d1, c)) {
                ++n;
                printf("插入成功\n");
            }
            else {
                printf("插入失败\n");
            }
        Case 7: // 删除指定位置的学生记录
            printf("请输入要删除的位置:");
            scanf("%d", &d1);
            if (ListDelete(L, d1)) {
                --n;
                printf("删除成功\n");
            }
            else {
                printf("删除失败\n");
            }
        Case 8: // 统计学生人数
            printf("已录入的学生个数为:%d\n\n", n);
            break;
        default:
            printf("无效选项\n");
        }
    }

    return 0;
}

今天就先到这了!!!

看到这里了还不给博主扣个:
⛳️ 点赞☀️收藏 ⭐️ 关注!

你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信呢秒回哦。

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

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

相关文章

【AI】命令行调用大模型

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 【AI】命令行调用大模型引入正文初始化项目撰写脚本全局安装 成果展示 【AI】命令…

Linux——共享内存

Linux——共享内存 什么是共享内存共享内存原理Linux下共享内存的接口创建/获取共享内存&#xff1a;shmgetftok函数 映射共享内存到进程地址空间&#xff1a;shmat 解除共享内存映射&#xff1a;shmdt删除共享内存段&#xff1a;shmctl 利用共享内存进行通信 我们之前学习了匿…

香港服务器怎么看是CN2 GT线路还是CN2 GIA线路?

不知道有没有小伙伴们注意过&#xff0c;很多人在租用香港服务器的时候都习惯性选择 CN2 线路&#xff1f;仿佛香港服务器是否采用 CN2 线路成为个人企业选择香港服务器的一个标准。其实&#xff0c;香港服务器有CN2、优化直连(163)、BGP多线(包含了国际和国内线路)&#xff0c…

Unity 刮刮乐(优化极简)

废话不多说上代码&#xff0c;上图片&#xff0c;欢迎对Unity有兴趣的伙伴和我一起探讨学习 using UnityEngine; using UnityEngine.UI;public class ScratchCardWithSpriteRenderer : MonoBehaviour {// 公开背景和遮罩的Sprite Renderer组件public SpriteRenderer background…

java复原IP 地址(力扣Leetcode93)

复原IP 地址 力扣原题链接 问题描述 有效 IP 地址正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 ‘.’ 分隔。 例如&#xff1a;“0.1.2.201” 和 “192.168.1.1” 是有效 IP 地址&#xff0c…

爬取b站音频和视频数据,未合成一个视频

一、首先找到含有音频和视频的url地址 打开一个视频&#xff0c;刷新后&#xff0c;找到这个包&#xff0c;里面有我们所需要的数据 访问这个数据包后&#xff0c;获取字符串数据&#xff0c;用正则提取&#xff0c;再转为json字符串方便提取。 二、获得标题和音频数据后&…

基于LSB(最低有效位)的图像水印算法,Matlab实现

博主简介&#xff1a; 专注、专一于Matlab图像处理学习、交流&#xff0c;matlab图像代码代做/项目合作可以联系&#xff08;QQ:3249726188&#xff09; 个人主页&#xff1a;Matlab_ImagePro-CSDN博客 原则&#xff1a;代码均由本人编写完成&#xff0c;非中介&#xff0c;提供…

【蓝桥杯第十四届省赛B】(部分详解)

【01串的熵】 https://www.lanqiao.cn/problems/3498/learning/?subject_code1&group_code4&match_num14&match_flow1&origincup #include <iostream> #include<cmath> using namespace std; int main() {double n23333333;double sum0;for(int…

【跟着CHATGPT学习硬件外设 | 04】ADC

本文根据博主设计的Prompt由CHATGPT生成&#xff0c;形成极简外设概念。 &#x1f680; 1. 概念揭秘 1.1 快速入门 模数转换器&#xff08;ADC&#xff0c;Analog-to-Digital Converter&#xff09;是一种将模拟信号转换为数字信号的电子设备。模拟信号通常表示物理测量的连…

Learning To Count Everything

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 摘要Abstract文献阅读&#xff1a;学习数一切东西1、研究背景2、提出方法3、模块详细3.1、多尺度特征提取模块3.2、密度预测模块 4、损失函数5、性能对比6、贡献 二…

mybatis标签解析教程

mybatis标签解析 标签结构 我们在mapper的xml文件中&#xff0c;使用动态SQL&#xff0c;那么这些标签<where>、<if>、<set>、<ForEach>、<Choose>、<Trim> 等是怎么解析的呢&#xff1f;我们先看包的结构 包结构中&#xff0c;script…

算法沉淀——拓扑排序

前言&#xff1a; 首先我们需要知道什么是拓扑排序&#xff1f; 在正式讲解拓扑排序这个算法之前&#xff0c;我们需要了解一些前置知识&#xff08;和离散数学相关&#xff09; 1、有向无环图&#xff1a; 指的是一个无回路的有向图。 入度&#xff1a;有向图中某点作为图…

微服务(基础篇-007-RabbitMQ部署指南)

目录 05-RabbitMQ快速入门--介绍和安装_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1LQ4y127n4?p65&vd_source60a35a11f813c6dff0b76089e5e138cc 1.单机部署 1.1.下载镜像 1.2.安装MQ 2.集群部署 2.1.集群分类 2.2.设置网络 视频地址&#xff1a; 05-Rab…

Topaz Gigapixel AI for Mac 图像放大软件

Topaz Gigapixel AI for Mac是一款专为Mac用户设计的智能图像放大软件。它采用了人工智能技术&#xff0c;特别是深度学习算法&#xff0c;以提高图像的分辨率和质量&#xff0c;使得图像在放大后仍能保持清晰的细节。这款软件的特点在于其能够将低分辨率的图片放大至高分辨率&…

银河麒麟V10:sudo: /usr/bin/sudo 必须属于用户 ID 0(的用户)并且设置 setuid 位

一、引起原因&#xff1a; sudo chmod -R 777 bin 修改了/usr/bin/sudo的权限&#xff0c;引发后续问题。 二、现象&#xff1a; sudo执行命令报错&#xff1a; sudo: /usr/bin/sudo 必须属于用户 ID 0(的用户)并且设置 setuid 位 三、解决方法&#xff08;知道root密码&…

Java复习第十四天学习笔记(CSS),附有道云笔记链接

【有道云笔记】十四 3.30 CSS https://note.youdao.com/s/3VormGXs 一、CSS定义和基本选择器 CSS定义&#xff1a;cascading style sheet 层叠样式表。 语法&#xff1a; 选择器 { 属性名1:属性值1; 属性名2:属性值2; 属性名3:属性值3; 属性名4:属性值4; } CSS使用&a…

经典永不过时 Wordpress模板主题

经得住时间考验的模板&#xff0c;才是经典模板&#xff0c;带得来客户的网站&#xff0c;才叫NB网站。 https://www.jianzhanpress.com/?p2484

基于大数据的学习资源推荐系统的设计与实现(论文+源码)_kaic

摘 要 本文首先实现了学习资源推送管理技术的发展&#xff0c;随后依照传统的软件开发流程&#xff0c;最先为系统挑选适用的语言和软件开发平台&#xff0c;依据需求分析开展控制模块制作和数据库查询构造设计&#xff0c;依据系统整体功能模块的设计&#xff0c;制作系统的功…

武汉星起航引领亚马逊跨境电商新浪潮,助推卖家向全球拓展

在全球化的浪潮中&#xff0c;跨境电商以其独特的魅力和无限潜力&#xff0c;正成为推动国际贸易发展的重要引擎。亚马逊&#xff0c;作为全球电商平台的佼佼者&#xff0c;以其卓越的技术、高效的服务和广阔的市场覆盖&#xff0c;引领着跨境电商的新风潮。而在这股风潮中&…

JUC并发编程——对于synchronized关键字的理解

现象&#x1f50d;&#xff1a; 两个线程对初始值为 0 的静态变量一个做自增&#xff0c;一个做自减&#xff0c;各做 5000 次&#xff0c;最后输出的 counter一定为0 吗&#xff1f; Slf4j(topic "c.Test17") public class Test17 {static int counter 0;public…