学籍管理

#define offsetof(TYPE, MEMBER) ((size_t) &(((TYPE *)0)->MEMBER))
#define container_of(ptr, type, member) ({                  \
    const typeof(((type *)0)->member) *__mptr = (ptr);      \
    (type *)((char *)__mptr - offsetof(type,member));       \
    })
#define DEBUG

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

struct list_chain {
    struct list_chain *next,*prev;
};
struct student {
    int sage;
    char sno[8];
    char sname[16];
    char sclass[8];
    struct list_chain list;
};

void list_insert(struct list_chain * head,struct list_chain * mychain);
void print_all_debug(struct list_chain *head,struct list_chain *tail);
void print_sort_chain(struct list_chain *head,struct list_chain *tail);
struct list_chain *list_find_sno(struct list_chain *head,char *sno);
void change_student_data(struct list_chain *head,char *sno);
void delete_node(struct list_chain *head,char *sno);
void add_data(struct list_chain *chain1);
int get_length(struct list_chain *head);

//Test Case
//5
//25 1000 HongPeng 45678
//80 9999 ZhangSan 77860
//18 0001 XiaoMing 66880
//60 0000 ZhongGou 99374
//46 9989 ZhuYuanL 00123

//Used for alter
//10 7777 HaHaHaHa 123456
// or
//10 9977 HaHaHaHa 123456
int main(){
    struct list_chain *list_head = (struct list_chain *)malloc(sizeof(struct list_chain));
    struct list_chain *list_tail = (struct list_chain *)malloc(sizeof(struct list_chain));
    memset(list_head,0,sizeof(struct list_chain));
    memset(list_tail,0,sizeof(struct list_chain));
    list_head->prev = list_tail;
    list_head->next = list_tail;
    list_tail->next = list_head;
    list_tail->prev = list_head;
#ifdef DEBUG
    // add && print
    add_data(list_head);
    printf("After add student\n");
    print_all_debug(list_head,list_tail);

    // search && print
    struct list_chain *searched_chain = list_find_sno(list_head,"9989");
    struct student *st = container_of(searched_chain,struct student,list);
    printf("\nAfter search for student with '9989' sno\n");
    printf("sage:%d sno:%s sname:%s sclass:%s\n",st->sage,st->sno,st->sname,st->sclass);

    // sort && print
    printf("\nPrintout sorted chain\n");
    print_sort_chain(list_head,list_tail);
    printf("\nAfter print sorted chain\n");
    print_all_debug(list_head,list_tail);

    // alter && print
    printf("\nPrint before altering\n");
    change_student_data(list_head,"9989");
    printf("\nPrint after altering\n");
    print_all_debug(list_head,list_tail);

    // delete && print
    printf("\nPrint before deleting\n");
    print_all_debug(list_head,list_tail);
    delete_node(list_head,"9977");
    printf("\nPrint after deleting\n");
    print_all_debug(list_head,list_tail);
#endif
    return 0;
}

void add_data(struct list_chain *chain1){
    int times;
    printf("Format [sage sno sname sclass]\n");
    printf("How many new students/teachers?\n");
    scanf("%d",&times);getc(stdin);
    for (int i = 0; i < times; i++) {
        struct student * tmp_st = (struct student *)malloc(sizeof(struct student));
        scanf("%d %s %s %s",&tmp_st->sage,tmp_st->sno,tmp_st->sname,tmp_st->sclass);getc(stdin);
        list_insert(chain1,&(tmp_st->list));
    }
}

void list_append(struct list_chain * tail,struct list_chain * mychain){
    mychain->next = tail->next;
    mychain->prev = tail;
    tail->next->prev = mychain;
    tail->next = mychain;
}

void list_insert(struct list_chain *head,
                 struct list_chain *mychain){
    mychain->prev = head;
    mychain->next = head->next;
    head->next->prev = mychain;
    head->next = mychain;
}

struct list_chain *list_find_sno(struct list_chain *head,char *sno){
    struct list_chain *mid_chain = head->next;
    while (mid_chain != head->prev) {
        struct student *st = container_of(mid_chain,struct student,list);
        if (!strcmp(sno,st->sno)) {
            return mid_chain;
        }
        mid_chain = mid_chain->next;
    }
    printf("This sno:%s is not found!\n",sno);
    return NULL;
}

void change_student_data(struct list_chain *head,char *sno){
    struct list_chain *chain = list_find_sno(head,sno);
    if (chain == NULL) {printf("Change node with sno:[%s] failure!",sno);return;}
    struct student *st = container_of(chain,struct student,list);
    printf("Format [sage sno sname sclass]\n");
    scanf("%d %s %s %s",&st->sage,st->sno,st->sname,st->sclass);
}

void delete_node(struct list_chain *head,char *sno){
    struct list_chain *chain = list_find_sno(head,sno);
    if (chain == NULL) {printf("Delete node with sno:[%s] failure!",sno);return;}
    struct list_chain *before = chain->prev,*after = chain->next;
    before->next = after;
    after->prev  = before;
    free(container_of(chain,struct student,list));
}

void print_sort_chain(struct list_chain *head,struct list_chain *tail){
    int length = get_length(head);
    for (int i = 0; i < length; i++) {
        char *sno = container_of(head->next,struct student,list)->sno;
        struct list_chain *mid_chain = head->next;
        while (mid_chain != tail) {
            char *mid_sno = container_of(mid_chain,struct student,list)->sno;
            if (strcmp(sno,mid_sno) > 0) {
                sno = mid_sno;
            }
            mid_chain = mid_chain->next;
        }
        struct list_chain *chain = &(container_of(sno,struct student,sno)->list);
        struct list_chain *before = chain->prev;
        struct list_chain *after = chain->next;
        before->next = after;
        after->prev  = before;
        list_append(tail,chain);
        struct student *st = container_of(chain,struct student,list);
        printf("sage:%d sno:%s sname:%s sclass:%s\n",st->sage,st->sno,st->sname,st->sclass);
    }
    // restore head-prev
    struct list_chain *ori_befor_head = head->prev;
    struct list_chain *ori_after_tail = tail->next;
    ori_befor_head->next = tail;
    tail->prev = ori_befor_head;
    tail->next = ori_after_tail;
    head->next = ori_after_tail;
    head->prev = tail;
    ori_after_tail->prev = head;
}

int get_length(struct list_chain *head){
    struct list_chain *mid_chain = head->next;
    struct list_chain *tail = head->prev;
    int length = 0;
    while (mid_chain != tail) {
        length += 1;
        mid_chain = mid_chain->next;
    }
    return length;
}

#ifdef DEBUG
void print_all_debug(struct list_chain *head,struct list_chain *tail){
    struct list_chain *mid_chain = head->next;
    while (mid_chain != tail) {
        struct student *st = container_of(mid_chain,struct student,list);
        printf("sage:%d sno:%s sname:%s sclass:%s\n",st->sage,st->sno,st->sname,st->sclass);
        mid_chain = mid_chain->next;
    }
}
#endif