链表实现学生管理系统

时间:2019-08-29
本文章向大家介绍链表实现学生管理系统,主要包括链表实现学生管理系统使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

makefile

main : main.o stu.o llist.o
    gcc -Wall -o $@ $^
clean :
    rm -rf main *.o

头文件

llist.h

#ifndef __LLIST_H
#define __LLIST_H

enum a
{
    HEADINSERT,
    TAILINSERT
};

typedef void (llist_print)(const void *data);
typedef int (llist_cmp)(const void *data, const void *cp);
typedef void LLIST;

LLIST *llist_handler(int size);

int llist_insert(LLIST *h, const void *data, int mode);

int llist_delect(LLIST *h, const void *data, llist_cmp cmp);

void *llist_find(LLIST *h, const void *data, llist_cmp cmp);

void *llist_display(LLIST *h, llist_print print);

void *llist_destroy(LLIST *h);

int llist_fetch(LLIST *handler, void *b_data, llist_cmp cmp, void *save);

int llist_output(LLIST *h, void *save);

#endif

stu.h

#ifndef __STU_H
#define __STU_H

#include "llist.h"

struct stu
{
    int id;
    char name[20];
    long int tel;
};

void insert_data(LLIST *handler);

int delect_data(LLIST *handler);

int    fetch_data(LLIST *handler);

int find_data(LLIST *handler);

void display_data(LLIST *handler);

void sort_data(LLIST *handler);

int save_data(LLIST *handler);

int read_data(LLIST *handler);

#endif

llist.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "llist.h"

struct llist_node
{
    struct llist_node *prev;
    struct llist_node *next;
    char data[0];
};

struct head_node
{
    int size;
    struct llist_node node;
};

LLIST *llist_handler(int size)
{
    struct head_node *handler = NULL;

    handler = malloc(sizeof(LLIST));
    if(handler == NULL)
        return NULL;
    handler->size = size;
    handler->node.prev = handler->node.next = &handler->node;
    
    return handler;
}

int llist_insert(LLIST *h, const void *data, int mode)
{
    struct head_node *handler = h;
    struct llist_node *newnode = NULL;
    struct llist_node *p = &handler->node;

    newnode = malloc(sizeof(struct llist_node) + handler->size);
    if(newnode == NULL)
        return -1;
    memcpy(newnode->data, data, handler->size);
    switch(mode)
    {
        case HEADINSERT :    break;
        case TAILINSERT :    p = p->prev;
                            break;
        default :            free(newnode);
                            break;
    }
    newnode->next = p->next;
    newnode->prev = p->next->prev;
    newnode->prev->next = newnode;
    newnode->next->prev = newnode;
    return 0;
}

struct llist_node *_find(LLIST *h, const void *data, llist_cmp cmp)
{
    struct head_node *handler = h;
    struct llist_node *cur = NULL;

    for(cur = handler->node.next; cur != &handler->node; cur = cur->next)
    {
        if(cmp(cur->data, data))
            return cur;
    }
    return NULL;
}

void *llist_find(LLIST *h, const void *data, llist_cmp cmp)
{
    struct head_node *handler = h;
    struct llist_node *find = NULL;

    find = _find(handler, data, cmp);
    if(NULL == find)
        return NULL;
    return find->data;
}

int llist_delect(LLIST *h, const void *data, llist_cmp cmp)
{
    struct head_node *handler = h;
    struct llist_node *find = NULL;

    find = _find(handler, data, cmp);
    if(NULL == find)
        return -1;
    find->prev->next = find->next;
    find->next->prev = find->prev;
    free(find);
}

void *llist_display(LLIST *h, llist_print print)
{
    struct head_node *handler = h;
    struct llist_node *cur = handler->node.next;

    while(cur != &handler->node)
    {
        print(cur->data);
        cur = cur->next;
    }
}

void *llist_destroy(LLIST *h)
{
    struct head_node *handler = h;
    struct llist_node *p = NULL;
    struct llist_node *cur = NULL;
    
    for(p = handler->node.next; p != &handler->node; p = p->next)
    {
        cur = p;
        p->next->prev = p->prev;
        p->prev->next = p->next;
        free(p);
        p = cur;
    }
    free(handler);
}

int llist_fetch(LLIST *h, void *b_data, llist_cmp cmp, void *save)
{
    struct head_node *handler = h;
    struct llist_node *cur = NULL;
    struct llist_node *find = NULL;

    find = _find(handler, b_data, cmp);
    if(NULL == find)
        return -1;
    memcpy(save, find->data, handler->size);
    find->next->prev = find->prev;
    find->prev->next = find->next;
    free(find);
}

int llist_output(LLIST *h, void *save)
{
    struct head_node *handler = h;
    struct llist_node *cur = handler->node.next;

    if(cur == &handler->node)
        return -1;

    cur->next->prev = cur->prev;
    cur->prev->next = cur->next;
    memcpy(save, cur->data, handler->size);
    free(cur);
}

stu.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "stu.h"

static int a, ret, b, bnum, num;
static char name[20];
static char bname[20];
static long int tel, lbnum, lnum;

void print(const void *data)    //打印函数
{
    const struct stu *p = data;
    printf("%d  %s  %ld\n", p->id, p->name, p->tel);
}

int id_cmp(const void *data, const void *cp)    //id对比函数
{
    const struct stu *p = data;
    const int *cur = cp;

    return !(p->id - *cur);
}

int tel_cmp(const void *data, const void *cp)
{
    const struct stu *p = data;
    const long int *cur = cp;

    return !(p->tel - *cur);
}

int name_cmp(const void *data, const void *cp)        //名字对比函数
{
    const struct stu *p = data;
    const char *cur = cp;

    return !(strcmp(cur, p->name));
}

void insert_data(LLIST *handler)                //增加数据函数
{
    struct stu data;
    struct stu *find = NULL;

    system("clear");
    printf("请输入学号:\n");
    scanf("%d", &num);
    find = llist_find(handler, &num, id_cmp);
    if(find != NULL)
    {
        printf("该学号已存在,请核对后从新输入!\n");
        sleep(2);
        return ;
    }
    data.id = num;
    printf("请输入学生姓名:\n");
    scanf("%s", name);
    memcpy(data.name, name, 20);
    printf("请输入学生电话:\n");
    scanf("%ld", &tel);
    data.tel = tel;
    ret = llist_insert(handler, &data, HEADINSERT);
    if(ret < 0)
        printf("未能成功添加学生信息。\n");
    else
        printf("成功添加学生信息。\n");
    sleep(2);
}


int delect_data(LLIST *handler)                //删除数据函数
{
LEAP :    
    printf("1.输入学号删除\t2.输入姓名删除\n");
    scanf("%d", &b);
    if(b == 1)
    {
        system("clear");
        printf("请输入要删除学生的学号:\n");
        scanf("%d", &num);
        ret = llist_delect(handler, &num, id_cmp);    
        if(ret < 0)
            return -1;
        else
            printf("成功删除学号为%d的学生信息。\n", num);
    }
    else if(b == 2)
    {
        system("clear");
        printf("请输入要删除学生的姓名:\n");
        scanf("%s", name);
        ret = llist_delect(handler, name, name_cmp);
        if(ret < 0)
            return -1;
        else
            printf("成功删除姓名为%s的学生信息\n", name);
    }
    else
    {
        system("clear");
        printf("输入错误,请重新输入\n");
        goto LEAP;
    }
}

int    fetch_data(LLIST *handler)            //修改数据函数,修改数据后不排序
{
    struct stu save;

LEAP1:        
    printf("请选择你要修改的信息:\n1.修改学号  2.修改姓名  3.修改电话\n");
    scanf("%d", &b);
    if(b == 1)
    {
        system("clear");
        printf("请输入你要修改的学号:\n");    
        scanf("%d", &bnum);
        printf("请输入新的学号:\n");
        scanf("%d", &num);
        ret = llist_fetch(handler, &bnum, id_cmp, &save);
        if(ret < 0)
            return -1;
        else
        {
            save.id = num;
            ret = llist_insert(handler, &save, HEADINSERT);
            if(ret < 0)
                return -2;
            goto PRINT;
        }
    }
    else if(b == 2)
    {
        system("clear");
        printf("请输入你要修改的学生姓名:\n");
        scanf("%s", bname);
        printf("请输入修改后的学生姓名:\n");
        scanf("%s", name);
        ret = llist_fetch(handler, bname, name_cmp, &save);
        if(ret < 0)
            return -1;
        else
        {
            memcpy(save.name, name, 20);
            ret = llist_insert(handler, &save, HEADINSERT);
            if(ret < 0)
                return -2;
            else
            goto PRINT;
        }
    }
    else if(b == 3)
    {
        system("clear");
        printf("请输入你要修改的电话:\n");    
        scanf("%ld", &lbnum);
        printf("请输入新的电话:\n");
        scanf("%ld", &lnum);
        ret = llist_fetch(handler, &lbnum, tel_cmp, &save);
        if(ret < 0)
            return -1;
        else
        {
            save.tel = lnum;
            ret = llist_insert(handler, &save, HEADINSERT);
            if(ret < 0)
                return -2;
            goto PRINT;
        }
    }
    else
    {
        system("clear");
        printf("输入错误,请重新输入\n");
        goto LEAP1;
    }
PRINT:
    printf("修改成功!该学生的最新信息为:\n");
    print(&save);
}

int find_data(LLIST *handler)        //查找数据函数
{
    struct stu *find = NULL;
LEAP:
    printf("请选择查找方式:\n1.通过学号查找\t2.通过姓名查找\n");
    scanf("%d", &a);
    if(a == 1)
    {
        system("clear");
        printf("请输入学号:\n");
        scanf("%d", &num);
        find = llist_find(handler, &num, id_cmp);
        if(ret < 0)
            return -1;
        goto PRINT;
    }
    else if(a == 2)
    {
        system("clear");
        printf("请输入姓名:\n");
        scanf("%s", name);
        find = llist_find(handler, name, name_cmp);
        if(ret < 0)
            return -1;
        goto PRINT;
    }
    else
    {
        system("clear");
        printf("输入错误, 请重新输入!\n");
        goto LEAP;
    }

PRINT:
    printf("已找到!\n");
    print(find);
}

void display_data(LLIST *handler)        //打印数据函数
{
    system("clear");
    llist_display(handler, print);
}

void sort_data(LLIST *handler)        //排序函数,上限100个
{
    struct stu save[100] = {};
    struct stu tmp;
    struct stu s;
    int i = 0, j = 0, a = 0;

    for(i = 0; i < 100; i++)
    {
        ret = llist_output(handler, &s);
        if(ret < 0)
            break;
        memcpy(&save[i], &s, sizeof(struct stu));
    }

    a = i;
    for(i = 0; i < 99; i++)
    {
        for(j = 0; j < 99 - i; j++)
        {
            if(save[j].id < save[j+1].id)
            {
                memcpy(&tmp, &save[j], sizeof(struct stu));
                memcpy(&save[j], &save[j+1], sizeof(struct stu));
                memcpy(&save[j+1], &tmp, sizeof(struct stu));
            }
        }
    }

    for(i = 0; i < a; i++)
    {
        ret = llist_insert(handler, &save[i], HEADINSERT);
        if(ret < 0)
            break;
    }
    printf("排序完成!\n");
    sleep(2);
}


int save_data(LLIST *handler)        //打印到文件
{
    FILE *fp = NULL;
    struct stu save;

    fp = fopen("data_save", "r+");
    if(fp == NULL)
        return -1;

    while(1)
    {
        ret = llist_output(handler, &save);
        if(ret < 0)
            break;
        ret = fprintf(fp, "%d\t\t\t%s\t\t\t%ld\n", save.id, save.name, save.tel);
        if(ret == EOF)
        {
            fclose(fp);
            perror("fprintf()");
            return -1;
        }
    }
    fclose(fp);
    fp = NULL;
    printf("向文件写入成功!\n");
    sleep(2);
}

int read_data(LLIST *handler)        //从文件导入链表
{
    FILE *fp = NULL;
    struct stu save;

    fp = fopen("data_save", "r+");
    if(fp == NULL)
        return -1;

    while(1)
    {
        ret = fscanf(fp, "%d%s%ld", &save.id, save.name, &save.tel);
        if(ret == EOF)
        {
            perror("fprintf()");
            break;
        }
//        print(&save);
        llist_insert(handler, &save, HEADINSERT);
    }
    fclose(fp);
    fp = NULL;
    printf("文件内容以存入链表!\n");
    sleep(2);
}

main.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "stu.h"
#include "llist.h"


int main(void)
{
    struct stu *data, *save;
    char d = 0;
    int a = 0, num = 0, ret = 0, b = 0, bnum = 0;
    int tel;
    FILE *fd = NULL;
    LLIST *handler = NULL;

    handler = llist_handler(sizeof(struct stu));
    if(NULL == handler)
        return -1;
/*    
    fd = fopen("data_save", "w+");
    if(fd == NULL)
    {
        perror("fopen");
        return -1;
    }

    ret = fprintf(fd, "%s\t\t\t%s\t\t\t%s\n", "学号", "姓名", "电话");
    if(ret == EOF)
    {
        fclose(fd);
        return -1;
    }
    
    fclose(fd);
    p = NULL;
*/
    while(1)
    {
        system("clear");
        printf("-----------------------------------------------------------\n");
        printf("---------------------学生管理系统--------------------------\n");
        printf("-----------------------------------------------------------\n");
        printf("1.增加数据\t2.删除数据\t3.修改数据\t4.查找数据\n5.打印数据\t6.排序数据\t7.保存文件\t8.读取文件\n9.退出系统\n");
        printf("请输入序号操作\n");
        scanf("%d", &a);

        switch(a)
        {
            case 9:    return 0;
            case 1:    insert_data(handler);
                    break;
            case 2:    ret = delect_data(handler);
                    if(ret < 0)
                        printf("删除失败!没有该学生信息。\n");
                    sleep(2);
                    break;
            case 3:    ret = fetch_data(handler);
                    if(ret == -1)
                        printf("修改失败!未找到该学生的信息。\n");
                    else if(ret == -2)
                        printf("修改失败!\n");
                    sleep(2);
                    break;
            case 4:    ret = find_data(handler);
                    if(ret < 0)
                        printf("未找到该学生信息。\n");
                    sleep(2);
                    break;
            case 5:    display_data(handler);
                    printf("按q退出\n");
                    getchar();
                    scanf("%c", &d);
                    if(d == 'q' || d == 'Q')
                        break;
            case 6: sort_data(handler);
                    break;
            case 7:    save_data(handler);
                    break;
            case 8: read_data(handler);
                    break;
            default:    printf("输入有误!\n");
                        sleep(3);
                        break;
        }

    }

    return 0;
}

原文地址:https://www.cnblogs.com/zjw2030/p/11428549.html