c语言数据结构实验:链表实现学生信息的储存

首先感谢ChatGPT给我提供的帮助

进入正题
本文作者同为大一新生,写这篇文章的目的是记录自己的学习经历,以及帮助一些稍有困难的同学理解数据结构,能力有限,如有错误请指出。本文基于严蔚敏老师的《数据结构与算法(c语言版 第二版)》创作。(建议学习的时候搭配着书看)
学习前提
1.本文需要有一定的链表基础,如果对链表不太了解,建议对链表的结构稍加学习之后再来看
2.你需要明确知道实际参数和形式参数之间的关系如果不知道可以看作者的这篇文c语言实际参数与形式参数

实验内容是这样的

定义一个包含学生信息(学号,姓名,成绩)的链表,使其具有如下功能:
(1) 根据指定学生个数,逐个输入学生信息;
(2) 逐个显示学生表中所有学生的相关信息;
(3) 根据姓名进行查找,返回此学生的学号和成绩;
(4) 根据指定的位置可返回相应的学生信息(学号,姓名,成绩);
(5) 给定一个学生信息,插入到表中指定的位置;
(6) 删除指定位置的学生记录;

代码与讲解如下

头文件

首先你需要的头文件有

#include <stdio.h>	//这个不需要解释了吧~~~
#include <stdlib.h>	//因为我们需要malloc函数分配内存和free函数释放内存,至于这个头文件的具体内容,建议自己百度
#include <string.h>	//和字符串有关的函数

链表的定义

其次就是链表结点的定义(关于链表的基本构造,如果你不会的话,可以去看看青岛大学王卓老师的课程)
可能有些人会疑惑,这个typedef是什么东西,这里之后可能会出一篇文章详细介绍,你可以先简单把它理解为:可以为某一类型自定义名称。或者你自己抽个时间细细的查一查

typedef struct 
{
    char no[15];	//学号
    char name[8];	//名字
    int chengji;	//成绩
}student;			

typedef struct Lnode    
{
    student date;   //数据域	,这是结构体嵌套哦~~在这个结构体中嵌套了一个student的结构体
    struct Lnode *next;     //指针域
}Lnode,*linklist;   //指向节点的指针

输入

其次就是输入学生的信息函数了
我这里把初始化和输入写到了一起。因为在一次程序中,你输入只有一次执行,之后的添加都是插入

linklist scanflist() //输入学生信息(头插法)定义一个返回值是链表头指针的函数
{
	//创建一个链表头结点L,并将其next指针设置为NULL,从而创建一个空链表。
    linklist L;	
    L=(linklist)malloc(sizeof(Lnode));//书中用的是new,但那是c++语法,我们用malloc分配内存
    L->next=NULL;
    //定义一个结构体指针p,以及变量n存储学生数量,并读入n。     
    linklist p; int n,i;   
    printf("请输入输入的学生数量:");   
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        p=(linklist)malloc(sizeof(Lnode));  //通过调用 malloc() 函数为指针p分配内存空间,大小为结构体Lnode的大小。也就是创建一个新结点*P
        printf("请输入学生信息:\n");
        printf("学号:");
        scanf("%s",p->date.no);
        printf("姓名:");
        scanf("%s",p->date.name);	//这里你需要注意一下是字符串输入,前面不加取地址符
        printf("成绩:");
        scanf("%d",&(p->date.chengji));
        p->next=L->next;    //使p插入头结点后
        L->next=p;		
    }
   return L;    //返回链表的头指针 L。
}

打印

之后是打印学生信息的代码,注意这里的传参是指针,这里设计到实际参数和形式参数的知识可以看我之前写的文章文章传送点我

void printlist(linklist L)   //打印学生信息
{
    linklist n;	//定义一个指针n,初始化为链表头节点的下一个节点,也就是第一个实际存储学生信息的节点。

    n=L->next;
    while (n)//使用while循环遍历整个链表,当n指向的节点不为空时,执行下列操作
    {	//打印n指向的结点里的内容
        printf("学号:%s\n姓名:%s\n成绩:%d\n",n->date.no,n->date.name,n->date.chengji);	
        n=n->next;
        printf("\n");
    }
    printf("打印完成,谢谢使用\n");
    printf("————————————————————————————\n");  
}

插入

接下来就是插入程序代码
这里需要用户输入插入的结点位置,所以为了防止用户输入一个超出当前链表总长的结点。我们需要对链表长度进行测量并与输入的结点位置进行比对。
我们设置两个结构体类型指针p,s
然后我们让p指针指向第i-1给结点,然后再把s指向的结点接在后面。之后再调整结点中的指针域使其连结起来。

void charulist(linklist L)		
{
    int i,j,n;
    linklist s,p;		//定义结构体指针p和s
    p=L;
    while (p!=NULL) 	//测量一下现在链表的长度
    {					//除非p为空while循环继续
        p=p->next;		//p指向下一个结点
        n++;			//n加1
    }
    printf("请输入插入的结点的位置");
    scanf("%d",&i);
    while (i>n)
    {
        printf("输入的结点超过总长,请重新输入");
        scanf("%d",&i);
    }
    p=L;j=1;
    while (p&&(j<i))    //让p指向第i-1个结点
    {       
        p=p->next;
        ++j;
    }
    s=(linklist)malloc(sizeof(Lnode));  //用s指向准备插入的结点,并给它分配一个内存空间
    printf("请输入学生信息:\n");	//后面的内容和输入同理
    printf("学号:");
    scanf("%s",s->date.no);
    printf("姓名:");
    scanf("%s",s->date.name);
    printf("成绩:");
    scanf("%d",&s->date.chengji);    
    s->next=p->next;	
    p->next=s;
    printf("信息插入成功\n");
    printf("——————————————————————————\n");
}

删除

然后是删除函数
大体和插入一样,都是找到想要的结点,之后的操作改成释放内存就好(free函数)

void deletelist(linklist L)
{
    int i,n=0,j;
    linklist p,q;
    p=L->next;
    while (p!=NULL)
    {
        p=p->next;
        n++;
    }
    printf("请输入要删除学生的位置结点:");
    scanf("%d",&i);
    while(n<i)
    {
        printf("输入的结点值超过总数,请重新输入要删除学生的位置结点:");
        scanf("%d",&i);
    }
    p=L; j=1;
    while((p->next)&&(j<i))	//注意这里p是指向第i-1个结点的
    {//这里和上面其实还有给小细节,你自己细细比对一下,然后体会一下为什么(自己思考一下)
        p=p->next;
        ++j;
    }	//到这为止上面都是一样的
    q=p->next;	//q指向第i跟结点
    p->next=q->next;	//p的指针域改为指向第i+1个结点(跳过第i个,也就是p指向的)
    free(q);	//利用free函数释放内存
    printf("删除成功!\n");
    printf("————————————————————————\n");
}

查找

输入要查找的学生姓名,然后将该值存储在字符数组name中。
用p指针指向链表中第一个节点的位置。
通过while循环遍历链表,每次使用strcmp函数比较字符串是否相同,如果不同,则将 p 指向下一个节点,同时将计数j加1。如果相同,跳出循环。
如果找到了目标节点,则打印出该节点中的学号和成绩信息。否则,打印出“该表中没有该学生的信息”。

void findlist(linklist L)//查找
{
    char name[10];
    int j=1;
    linklist p;
    printf("请输入查找学生的姓名:");
    scanf("%s",name);
    p=L->next;
    while(p&&strcmp(p->date.name,name)!=0)	//这里是strcmp函数是字符串的函数,如果忘记了可以去复习一下
    {//它用来比较字符串的大小是否相同(当然这里的大小是字典序而不是长度,别弄混了)
        p=p->next;
        j++;
    }//跳出循环的条件分别是:p为空(走到链表底了)和找到了符合条件的结点
    if(p)//如果p不为空(也就是p找到了)
        printf("该学生的信息:\n学号:%s\n成绩:%d\n",p->date.no,p->date.chengji);
    else
        printf("该表中没有该学生的信息。");
}

主函数

终于完活了

int main()
{
    linklist L;
    int k,n;
    L=scanflist();
    printf("输入成功\n");
    printf("——————————————————————————————\n");
    while (1)
    {
        printf("使用服务输入1,结束程序输入0\n");
        scanf("%d",&k);
        if(k==1)
        {
            printf("1-打印所有学生信息\n2-插入学生信息\n3-删除学生信息\n4-姓名查找学生\n0-退出\n");
            printf("请输入使用的项目\n");
            scanf("%d",&n);
            switch (n)
            {
            case 0:printf("已返回上一界面\n");break;
            case 1:printlist(L);break;
            case 2:charulist(L);break;
            case 3:deletelist(L);break;
            case 4:findlist(L);break;
            }
        }
        else  
        {   if(k==0)
            {
                printf("谢谢使用");break;
            }
            else
                printf("指令错误,请重新输入\n");
        }
    }   
    
}

谢谢阅读,如果对你有帮助的话可以点个关注点个赞哦

  • 25
    点赞
  • 91
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值