学生管理系统(链表)的简单实现

#include <stdio.h>
#include<string.h>
#include<malloc.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 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);

     //每个新创建的节点的next域都初始化为NULL
     l->next = NULL;
}

void inputStudentNo(char s[],char no[]){
    printf("请输入要%s的学生学号:",s);
    scanf("%s",no);
}

void displayNode(Link head){
   // 填写代码,根据传入的链表head头指针,扫描链表显示所有节点的信息
   Link p = (Link)malloc(sizeof(Node));//创建指针p遍历链表
   p = head->next;//头节点的下一个j节点赋值给p
   int i = 0;
   while(p != NULL)
   {
       i++;
       printf("第%d个学生姓名:%s\n", i, p->data.studentName);//打印学生姓名
       printf("第%d个学生学号:%s\n", i, p->data.studentNo);//打印学生学号
       printf("\n");
       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;//将q指针的下一个结点指向node
                node->next = p;//node的下一个结点指向p,完成插入
                return true;
            }
            else if(strcmp(node->data.studentNo, p->data.studentNo) == 0)//如果等于返回错误,表示已存在该学号
            {
                return false;
            }
            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);
    Link p,q;//创建两个指针遍历链表
    p = head->next;
    q = head;
    while(p!=NULL)
    {
        if(strcmp(p->data.studentNo, no) == 0)//如果相关表示找到了
        {
            q->next = p->next;//把p的下一个结点赋值给q的下一个结点
            free(p);//释放p指向的空间
            return true;
        }
        p = p->next;//没找到继续往下搜索
        q = q->next;
    }
    return false;//遍历链表找不到返回false
}

bool queryNode(Link head){
    // 按照给定的学号查询学生记录,如果查找成功返回true,如果没找到学号返回false

    //输入要处理的学号
    char no[NO_LENGTH];
    inputStudentNo("查找",no);
    Link p = head->next;
    while(p != NULL)
    {
         if(strcmp(p->data.studentNo, no) == 0)//如果相关表示找到了
        {
            printf("学生姓名:%s\n", p->data.studentName);//打印学生姓名
            printf("学生学号:%s\n", p->data.studentNo);//打印学生学号
            return true;
        }
        p = p->next;
    }
    return false;
}

bool modifyNode(Link head){
    // 按照给定的学号找到学生记录节点,如果修改成功返回true,如果没找到学号返回false
    //输入要处理的学号
    char no[NO_LENGTH];
    char name[NO_LENGTH];
    inputStudentNo("修改",no);
    Link p = head->next;
    while(p != NULL)
    {
         if(strcmp(p->data.studentNo, no) == 0)//如果相关表示找到了
        {
            printf("请输入学生新的姓名:");
            scanf("%s", name);
            strcpy(p->data.studentName, name);
            return true;
        }
        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;
    int i = 0;
    //遍历链表,用free语句删除链表中用malloc建立起的所有的节点
    while(head != NULL)
    {
        i++;
        q = head;
        head = head->next;
        free(q);
        printf("第%d个节点删除\n", i);
    }
}

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");
                system("pause");//暂停系统函数
                system("cls");//清屏系统函数
            }
            else
            {
                printf("学号已存在,请重新输入\n");
                system("pause");//暂停系统函数
                system("cls");//清屏系统函数
            }
            break;
        case 2:
            //删除学生记录
            if(deleteNode(head))
            {
                printf("成功删除一个学生记录。\n\n");
                system("pause");//暂停系统函数
                system("cls");//清屏系统函数
            }
            else
            {
                printf("没有找到要删除的学生节点。\n\n");
                system("pause");//暂停系统函数
                system("cls");//清屏系统函数
            }

            break;
        case 3:
            //查询学生记录
            if(queryNode(head))
            {
                printf("成功找到学生记录。\n\n");
                system("pause");//暂停系统函数
                system("cls");//清屏系统函数
            }
            else
            {
                printf("没有找到要查询的学生节点。\n\n");
                system("pause");//暂停系统函数
                system("cls");//清屏系统函数
            }

            break;
        case 4:
            //修改学生记录
            if(modifyNode(head))
            {
                printf("成功修改一个学生记录。\n\n");
                system("pause");//暂停系统函数
                system("cls");//清屏系统函数
            }
            else
            {
                printf("没有找到要修改的学生节点。\n\n");
                system("pause");//暂停系统函数
                system("cls");//清屏系统函数
            }
            break;
        case 5:
            //统计学生人数
            count = countNode(head);
            printf("学生人数为:%d\n\n",count);
            system("pause");//暂停系统函数
            system("cls");//清屏系统函数
            break;
        case 6:
            //显示学生记录
            displayNode(head);
            system("pause");//暂停系统函数
            system("cls");//清屏系统函数
            break;
        case 7:
            //退出前清除链表中的所有结点
            clearLink(head);
            return 0;
        default:
            printf("输入不正确,应该输入0-7之间的数。\n\n");
            system("pause");//暂停系统函数
            system("cls");//清屏系统函数
            break;
        }
    }
    return 0;
}
以上代码是在懒猫老师的代码基础上完善的,也推荐大家去关注懒猫老师的b站和知乎,真的是一个c语言和数据结构讲得特别好且声音好听的老师

懒猫老师-C语言-链表作业1:学生管理系统(代码模板) - 知乎

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值