C语言加链表实现学生信息管理系统

简介: 用C语言加链表的知识实现简单的学生信息管理系统。(可以自己完善添加数据库,文件流等操作)
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
#include<stdbool.h>
#define NO_LENGTH 20
#define NAME_LENGTH 11

typedef struct Student {
    char number[NO_LENGTH]; //学号
    char name[NAME_LENGTH]; //姓名
    char sex[6];            //性别
    int age;                //年龄
    char phone[NO_LENGTH];  //手机号
    char box[NO_LENGTH];    //邮箱
    double grade;           //成绩
} st;

typedef struct node {
    struct Student data;
    struct node* next;
} Node,*Link;

//提示菜单:
void myMenu() {
    printf("* * * * * * * * * * 菜     单 * * * * * * * * * *\n");
    printf("     1 增加学生记录            2 删除学生记录                     \n");
    printf("     3 查找学生记录            4 修改学生记录                     \n");
    printf("     5 统计学生人数            6 显示学生记录                     \n");
    printf("     7 学生成绩排名            8 退出系统          \n");
    printf(" * * * * * * * * * * * * * * * * * * * * * * * *\n");
}

//尾插:按顺序存放
Link newList(struct Student list[],int n) {
    Link head = malloc(sizeof(Node));
    head->next = NULL;
    Link rear = head;
    for(int i = 0; i < n; i++) {
        Link node = malloc(sizeof(Node));
        node->data = list[i];
        node->next = NULL;
        rear->next = node;
        rear = node;
    }
    return head;
}

//遍历:
void displayNode(Link head) {
    Link p = head->next;
    int count = 0;
    while(p != NULL) {
        printf("\n第%d个学生的学号、姓名、性别、年龄分别是:%s %s %s %d\n",
               count+1,p->data.number,p->data.name,p->data.sex,p->data.age);
        printf("手机号是:%s , 邮箱是: %s,总成绩是:%.2f\n",p->data.phone,p->data.box,p->data.grade);
        count++;
        p = p->next;
    }
    printf("\n");
}

//删除记录:(查学号删除)
bool deleteNode(Link head,char number[]) {
    if(head == NULL || head->next == NULL) {
        return false;
    }
    Link p = head->next;
    Link q = head;
    while(p != NULL) {
        if(strcmp(p->data.number,number) == 0) {
            q->next = p->next;
            free(p);
            return true;
        } else {
            q = p;
            p = p->next;
        }
    }
    return false;
}


//选择记录插入:
bool insertNode(Link head,int i,struct Student newdata) {
    Link p = head;
    int count = 1;
    while(p != NULL && count < i) {
        p = p->next;
        count++;
    }
    if(p == NULL) {
        return false;
    } else {
        Link node = malloc(sizeof(Node));
        node->data = newdata;
        node->next= p->next;
        p->next = node;
        return true;
    }
}

//按学生学号大小增加学生记录:
void inputStudent(Link l) {
    printf("请分别输入学生的学号、姓名、性别、年龄、手机号、邮箱、总成绩:\n");
    scanf("%s%s%s%d%s%s%lf",l->data.number,l->data.name,l->data.sex,&l->data.age,
          l->data.phone,l->data.box,&l->data.grade);
    //每个新创建的节点的next域都初始化为NULL
    l->next = NULL;
}

//按学号大小插入新结点
bool addNode(Link head) {
    Link p = head->next;
    Link q = head;      //q指向head后面的第一个有效节点
    Link node = malloc(sizeof(Node));

    inputStudent(node);

    if(head->next == NULL)  //没有数据时插入第一个数据
        head->next = node;
    else {
        while(p != NULL) {
            if (strcmp(node->data.number,p->data.number) < 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;
}

//统计学生人数:
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;
    while(head->next != NULL) {
        q = head;
        free(q);
        head = head->next;
    }
    free(head);
}

//查询学生记录
bool queryNode(Link head) {
    Link p = head->next;
    int key;
    printf("输入key(1~5),查询方式(1:姓名 2:学号 3:手机号 4:邮箱 5:年龄范围) :");
    scanf("%d",&key);

    if(key != 5) {

        char value[20];
        printf("\n请输入查询关键词:");
        scanf("%s",value);
        char middle[NO_LENGTH];
        switch(key) {
            case 1:
                strcpy(middle,p->data.name);
                break;
            case 2:
                strcpy(middle,p->data.number);
                break;
            case 3:
                strcpy(middle,p->data.phone);
                break;
            case 4:
                strcpy(middle,p->data.box);

        }
        while(p != NULL) {
            if(strcmp(middle,value) == 0)  {
                printf("\n查询成功!\n");
                printf("学生信息:姓名:%s 学号:%s 性别:%s 年龄:%d \n手机号:%s 邮箱:%s 总成绩:%.2f\n",
                       p->data.name,p->data.number,p->data.sex,p->data.age,p->data.phone,p->data.box,p->data.grade);
                printf("\n");
            }
            p = p->next;
            if(p != NULL) {
                if(key == 1) strcpy(middle,p->data.name);
                else if(key == 2) strcpy(middle,p->data.number);
                else if(key == 3) strcpy(middle,p->data.phone);
                else if(key == 4) strcpy(middle,p->data.box);
            }
        }

    }

    //指定年龄范围查询:
    else {
        int age1,age2;
        int key = 0;
        printf("请输入年龄范围:");
        scanf("%d%d",&age1,&age2);
        while(p != NULL) {
            if(age1 <= p->data.age && p->data.age <= age2) {
                printf("\n查询成功!\n");
                key = 1;//说明已经有找到的
                printf("学生信息:姓名:%s 学号:%s 性别:%s 年龄:%d \n手机号:%s 邮箱:%s 总成绩:%.2f\n",
                       p->data.name,p->data.number,p->data.sex,p->data.age,p->data.phone,p->data.box,p->data.grade);
                printf("\n");
            }
            p = p->next;
        }
        if(key == 1) {
            return true;
        }
    }
    return false;
}

//修改学生信息
bool modifyNode(Link head) {
    Link p = head->next;
    char value[20];
    printf("请输入你想要修改记录的学生姓名:");
    scanf("%s",value);

    while(p != NULL) {
        if(strcmp(p->data.name,value) == 0) {
            printf("请重新输入学生的信息:\n");
            printf("输入学生的学号、姓名、性别、年龄:\n");
            scanf("%s%s%s%d",p->data.number,p->data.name,p->data.sex,&p->data.age);
            printf("输入学生的手机号、邮箱、总成绩:\n");
            scanf("%s%s%lf",p->data.phone,p->data.box,&p->data.grade);
            break;
        }
        p = p->next;
    }
    return true;
}

//输出成绩排名
bool stuScore(Link head,double data[NO_LENGTH]) {
    Link p = head->next;
    if(p == NULL) {
        return false;
    }

    int i = 0,key = 0;
    while(p != NULL) {
        data[i] = p->data.grade;
        i++;
        p = p->next;
    }

    bubblesort(data,i);
    i = 0;
    for(p = head->next; p != NULL; p = p->next) {
        if(p->data.grade == data[i]) {
            printf("第%d名:学号:%s 姓名:%s 性别:%s 总成绩:%.2f\n",i+1,p->data.number,p->data.name,p->data.sex,p->data.grade);
            p = head;
            i++;
        }
    }
    return true;
}

//冒泡排序
void bubblesort(double array[],int array_size) {
    int exchange;
    for(int pass = 1; pass < array_size; pass++) {
        exchange = 0;
        for(int i = 0; i < array_size - pass; i++) {
            if(array[i] < array[i+1]) {
                double temp = array[i];
                array[i] = array[i+1];
                array[i+1] = temp;
                exchange = 1;
            }
        }
        if(exchange == 0) break;
    }
}

int main() {

    //输入学生数据:
    int arraysize;
    printf("输入您想要记录的学生人数:");
    scanf("%d",&arraysize);
    st list[100];
    for(int i=0; i < arraysize; i++) {
        printf("第%d个学生的学号、姓名、性别、年龄、手机号、邮箱、总成绩:\n",i+1);
        scanf("%s%s%s%d%s%s%lf",list[i].number,list[i].name,list[i].sex,&list[i].age,
              list[i].phone,list[i].box,&list[i].grade);
        printf("\n");
    }
    printf("\n");

    Link head = newList(list,arraysize);  //引入头部
    double data[NO_LENGTH];  //用于作成绩排名
    int count;
    int select;
    while(1) {
        myMenu();
        printf("\n请输入你的选择(1-8):");  //显示提示信息
        scanf("%d",&select);
        switch(select) {
            case 1:
                //增加学生记录
                if(addNode(head))
                    printf("成功插入一个学生记录。\n\n");
                break;
            case 2:
                //删除学生记录
                printf("输入要修改记录的学生学号:");
                char number[NO_LENGTH];
                scanf("%s",number);
                if(deleteNode(head,number))
                    printf("成功删除一个学生记录。\n\n");
                else
                    printf("没有找到要删除的学生节点。\n\n");
                break;

            case 3:
                //查询学生记录
                if(queryNode(head))
                    printf("无法找到这位学生!\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:
                //显示学生成绩排名
                stuScore(head,data);
                break;
            case 8:
                //退出前释放内存空间
                clearLink(head);
                return 0;
            default:
                printf("输入不正确,请输入1-8之间的数!\n\n");
                break;
        }
    }
    return 0;
}
目录
相关文章
|
20天前
|
C语言
对链表使用插入排序的C语言实现示例
对链表使用插入排序的C语言实现示例
|
1月前
|
C语言
C语言循环链表讲解
C语言循环链表讲解
19 0
|
1月前
|
存储 C语言
C语言线性链表讲解
C语言线性链表讲解
18 0
|
1月前
|
存储 C语言
C语言双向链表讲解
C语言双向链表讲解
17 0
|
1月前
|
存储 C语言 索引
在C语言中静态链表
在C语言中静态链表
17 1
|
1月前
|
存储 算法 C语言
在C语言中的动态链表
在C语言中的动态链表
9 0
|
1月前
|
前端开发 C语言
c语言中的链表
c语言中的链表
9 1
|
1月前
|
C语言
【C语言】Leetcode 206.反转链表
【C语言】Leetcode 206.反转链表
17 0
|
1月前
|
C语言
【C语言】Leetcode 876. 链表的中间节点
【C语言】Leetcode 876. 链表的中间节点
15 0
|
1月前
|
算法
LeetCode刷题---19. 删除链表的倒数第 N 个结点(双指针-快慢指针)
LeetCode刷题---19. 删除链表的倒数第 N 个结点(双指针-快慢指针)