2

学生管理系统双链表_阿军在学习的技术博客_51CTO博客

 8 months ago
source link: https://blog.51cto.com/u_16425777/9186727
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

学生管理系统双链表

精选 原创

GUO_战军 2024-01-10 22:13:40 ©著作权

文章标签 链表 赋值 #define 文章分类 代码人生 私藏项目实操分享 阅读数246

#include "stdio.h"
#include "stdlib.h"
#include "string.h"

#define RD_NO       (1<<0)
#define RD_NAME     (1<<1)
#define RD_SEX      (1<<2)
#define RD_SCORE    (1<<3)

//描述1个学生的属性
struct STUDENT  
{    
    int no;    
    char name[64];    
	char sex;    
    float score;  
};
//创建链表的节点数据结构
struct _node
{
    struct STUDENT student;//该节点的数据域
    struct _node *prev;    //该节点的指针域 -- 保存上一个节点
    struct _node *pnext;   //该节点的指针域 -- 保存下一个节点
};
void GetInfo(struct  STUDENT *p,unsigned char flag);
int Menu(void);
int Link_Add(struct _node *p1);
int ShowAll(struct _node *p1);
int Link_Find(struct _node*p1);
int Link_Change(struct _node *p1);
int Link_Del(struct _node *p1);
//指向头节点的指针变量
struct _node *phead = NULL;
int main()
{
    int no;
    while(1){
        no= Menu();
        switch(no)
        {
            case 1:Link_Add(phead);break;
            case 2:Link_Del(phead);break;
            case 3:Link_Change(phead);break;
            case 4:Link_Find(phead);break;
            case 5:break;
            case 6:ShowAll(phead);break;
        }
    }
}
/*
菜单
参数:无
返回:输入的菜单选项
*/
int Menu(void)
{
    int no;
p1:
    printf("**学生管理系统**\n");
    printf("1 添加学生     \n");
    printf("2 删除学生     \n");
    printf("3 修改学生     \n");
    printf("4 查找学生     \n");
    printf("5 成绩排序     \n");
    printf("6 打印所有信息  \n");
    printf("请输入选项:");
    scanf("%d",&no);
    if(no >= 1 && no <= 6)
        return no;
    printf("输入有误,重新输入\n");
    goto p1;
}
/*
函数功能:给链表中添加新的新节点
参数:p1 -- 保存链表头的地址
返回值:0 -- 成功
      >1 -- 失败
*/
/*
int Link_Add(struct _node *p1)
{
    //1.开辟新的节点,使用pnew指向该新的节点
    struct _node *pnew = malloc(sizeof(struct _node));
    //2.1给节点的数据域赋值
    GetInfo(&pnew->student,RD_NO|RD_NAME|RD_SEX|RD_SCORE);
    //2.2给节点的指针域赋值
    pnew->pnext = NULL;
    //3.把新的节点添加到链表中去
    //3.1 链表为空
    if(phead == NULL){
        phead = pnew;
        return 0;
    }else//尾插法
    {
        //找到链表尾 -- 根据节点的指针域是否为NULL
        while(p1->pnext != NULL){
            p1 = p1->pnext;
        }
        //把新节点添加到链表最后节点的后面(新的节点地址给上一个最后1个节点的指针域)
        p1->pnext = pnew;
        return 0;
    }
}*/
/*
函数功能:给链表中添加新的新节点
参数:p1 -- 保存链表头的地址
返回值:0 -- 成功
      >1 -- 失败
*/
/*
int Link_Add(struct _node *p1)
{
    //1.开辟新的节点,使用pnew指向该新的节点
    struct _node *pnew = malloc(sizeof(struct _node));
    //2.1给节点的数据域赋值
    GetInfo(&pnew->student,RD_NO|RD_NAME|RD_SEX|RD_SCORE);
    //2.2给节点的指针域赋值
    pnew->pnext = NULL;
    //3.把新的节点添加到链表中去 -- 头插法
    //3.1 原来第一个节点的地址给新节点的指针域
    pnew->pnext = phead;
    phead = pnew;
}*/
/*
函数功能:给链表中添加新的新节点
参数:p1 -- 保存链表头的地址
返回值:0 -- 成功
      >1 -- 失败
*/
int Link_Add(struct _node *p1)
{
    //1.开辟新的节点,使用pnew指向该新的节点
    struct _node *pnew = malloc(sizeof(struct _node));
    //2.1给节点的数据域赋值
    GetInfo(&pnew->student,RD_NO|RD_NAME|RD_SEX|RD_SCORE);
    //2.2给节点的指针域赋值
    pnew->pnext = NULL;
    pnew->prev = NULL;
    //3.把新的节点添加到链表中去 -- 中间插入
    //3.1 是否为空链表
    if(phead == NULL){
        phead = pnew;//直接放到第一个节点位置
        return 0;
    }
    //3.2 查找位置,进行插入
    while(p1 != NULL){
        if(pnew->student.no < phead->student.no)//上来比第一个节点数据小
        {
            phead->prev = pnew;
            pnew->pnext = phead;
            phead = pnew;
            return 0;
        }
        if(pnew->student.no > p1->student.no){//中间
            if(p1->pnext == NULL)//链表末尾
            {
                pnew->prev = p1;
                p1->pnext = pnew;
            }else if(pnew->student.no < p1->pnext->student.no)//中间
            {   //修改插入节点的指针域
                pnew->prev = p1;
                pnew->pnext = p1->pnext;
                //修改下一个节点(prev)
                p1->pnext->prev = pnew;
                //修改上一个节点(pnext)
                p1->pnext = pnew;
                return 0;
            }
        }
        p1 = p1->pnext;
    }
}
/*
函数功能:打印链表中所有节点信息
参数:链表头传递进来
返回值:0 -- 成功
      >0 -- 失败
*/
int ShowAll(struct _node *p1)
{
    printf("打印所有学生信息操作……\n");
    printf("学号\t姓名\t性别\t成绩\n");
    while(p1 != NULL){
        printf("%d\t",p1->student.no);
        printf("%s\t",p1->student.name);
        printf("%c\t",p1->student.sex);
        printf("%f\n",p1->student.score);
        p1 = p1->pnext;
    }
}
/*
从链表中查找某个信息
参数:p1 -- 链表头
返回值:0 -- 成功
      >0 -- 失败
*/
int Link_Find(struct _node*p1)
{
    struct STUDENT temp={0};//保存要查找的信息
    GetInfo(&temp,RD_NO|RD_NAME);
    //循环比较学号
    while(p1 != NULL)
    {
        if(p1->student.no == temp.no){
            if(strcmp(p1->student.name,temp.name)==0){
                printf("找到该学生,信息如下:\n");
                printf("%d\t",p1->student.no);
                printf("%s\t",p1->student.name);
                printf("%c\t",p1->student.sex);
                printf("%f\n",p1->student.score);
                return 0;
            }else{
                printf("学号正确,姓名不对\n");
            }
        }
        p1 = p1->pnext;
    }
    printf("查无此人\n");
    return 1;
}
/*
修改链表节点的内容
参数:p1 -- 指向链表头
返回值:0 -- 正确
      >0 -- 错误
*/
int Link_Change(struct _node *p1)
{
    struct STUDENT temp={0};
    GetInfo(&temp,RD_NO|RD_NAME);
    while(p1 != NULL){
        if(p1->student.no == temp.no){
            if(strcmp(p1->student.name,temp.name)==0){
                GetInfo(&temp,RD_NO|RD_NAME|RD_SEX|RD_SCORE);
                p1->student = temp;
                return 0;
            }
        }
        p1 = p1->pnext;
    }
    printf("查无此人\n");
    return 1;
}
/*
删除链表中某个节点
p1 -- 链表头
返回值: 0 -- 成功
      >0 -- 失败
       1 -- 链表为空
       2 -- 链表中查询不到
*/
int Link_Del(struct _node *p1)
{
    if(p1 == NULL){//空链表
        return 1;//链表为空
    }
    struct STUDENT temp={0};
    GetInfo(&temp,RD_NO);
    struct _node *pdel = NULL;//保存要删除节点的首地址
    while(p1 != NULL){
        if(p1->student.no == temp.no)
        {
            pdel = p1;//pdel保存要删除节点的首地址
            if(pdel->prev == NULL && pdel->prev == NULL)
            {
                phead = NULL;
                free(pdel);
                return 0;
            }
            //前一个节点的pnext变化
            if(pdel->prev != NULL)//中间
                pdel->prev->pnext = pdel->pnext;
            else//代表头节点
            {
                pdel->pnext->prev = NULL;//下一个节点的prev为空
                phead = pdel->pnext;     //下一个节点作为了链表头
            }
            //后一个节点的prev变化
            if(pdel->pnext != NULL)
                pdel->pnext->prev = pdel->prev;
            else{
                //上一给节点pnext变为NULL -- 作为链表尾
                pdel->prev->pnext = NULL;
            }
            free(pdel);
            return 0;
        }
        p1 = p1->pnext;
    }
    return 2;
}
/*
flag = 相应的选项是否允许输入
[0]位 -- no_flag    1--允许输入 0 -- 不允许输入
[1]位 -- name_flag  1--允许输入 0 -- 不允许输入
[2]位 -- sex_flag   1--允许输入 0 -- 不允许输入
[3]位 -- score_flag 1--允许输入 0 -- 不允许输入
*/
void GetInfo(struct  STUDENT *p,unsigned char flag)
{
    if(flag & (1<<0)){
        printf("请输入学号:");
        scanf("%d",&p->no);
    }
    if(flag & (1<<1)){
        printf("请输入姓名:");
        scanf("%s",p->name);
    }
    if(flag & (1<<2)){
        printf("请输入性别:");
        getchar();
        scanf("%c",&p->sex);
    }
    if(flag &(1<<3)){
        printf("请输入成绩:");
        scanf("%f",&p->score);
    }
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK