C 如何创建指向另一个链表的链表?

C 如何创建指向另一个链表的链表?,c,linked-list,C,Linked List,我做这个项目是为了管理每门学科注册的学生。 该系统由科目链表和学生链表组成。每个科目都有一个供学生使用的指针链接列表。 每个学生都有一个指向各自科目的指针列表。 所有链接列表都没有标题。 我试图创建函数来建立指向每个学生主题的指针列表,但我不知道如何创建它 到目前为止,我拥有的结构是: typedef struct node_subject * ListSubjects; typedef struct node_subject { char *name; struct node_

我做这个项目是为了管理每门学科注册的学生。 该系统由科目链表和学生链表组成。每个科目都有一个供学生使用的指针链接列表。 每个学生都有一个指向各自科目的指针列表。 所有链接列表都没有标题。 我试图创建函数来建立指向每个学生主题的指针列表,但我不知道如何创建它

到目前为止,我拥有的结构是:

typedef struct node_subject * ListSubjects;
typedef struct node_subject {
    char *name;
    struct node_ptrStudent *Students;
    ListSubjects next;
}NodeSubject;

typedef struct node_student * ListStudents;
typedef struct node_student {
    char *name;
    int num;
    struct node_ptrSubject *Subjects;
    ListStudents next;
}NodeStudent;

typedef struct node_ptrSubject * ListPtrSubjects;
typedef struct node_ptrSubject {
    ListSubjects subjects;
    ListPtrSubjects next;
}ListPtrSubjects;

typedef node_ptrStudent * ListPtrStudents;
typedef struct node_ptrStudent {
    ListStudents student;
    ListPtrStudents next;
}ListPtrStudents;

void createListPtrSubjects (ListSubjects);

Linux内核风格说“对结构和指针使用typedef是一个错误。”;不管你是否同意这一点,我认为你必须要有许多
typedef
;这有点让人困惑

如果你在编程一个关系数据库,你是这样的,这将是一个关联实体;看见此外,请确保您的主题具有主键

比如说,

#include <stdlib.h> /* EXIT_ realloc */
#include <limits.h> /* INT_MAX */
#include <errno.h>  /* errno */
#include <stdio.h>  /* perror printf */
#include <assert.h> /* assert */

struct Subject {
    int id; /* Primary key. */
    const char *name;
    struct Takes *takes_head;
};

struct Student {
    int id; /* Primary key. */
    const char *name;
    struct Takes *takes_head;
};

/* (Weak) Associative entity. */
struct Takes {
    int subject_id, student_id; /* Compound key. */
    struct Takes *next_subject, *next_student;
};

static struct School {
    struct Subject *subjects;
    int subjects_no;
    struct Student *students;
    int students_no;
} school;

static struct Subject *lookup_subject(const int id) {
    if(id >= school.subjects_no) return 0;
    return school.subjects + id;
}

static struct Subject *add_subject(const char *name) {
    struct Subject *subjects, *s;
    assert(name);
    if(school.subjects_no == INT_MAX) { errno = ERANGE; return 0; }
    /* fixme: realloc is slow; eg, double capacity. */
    if(!(subjects = realloc(school.subjects,
        sizeof *school.subjects * (school.subjects_no + 1)))) return 0;
    school.subjects = subjects;
    s = school.subjects + school.subjects_no;
    s->id = school.subjects_no;
    s->name = name;
    s->takes_head = 0;
    school.subjects_no++;
    return s;
}

/* May output in a static buffer. */
static const char *subject_to_string(const int id) {
    struct Subject *const subject = lookup_subject(id);
    static char str[256] = ""; /* Static buffer. */
    if(!subject) { sprintf(str, "<subject id %d>", id); return str; }
    return subject->name;
}

static struct Student *lookup_student(const int id) {
    if(id >= school.students_no) return 0;
    return school.students + id;
}

static struct Student *add_student(const char *name) {
    struct Student *students, *s;
    assert(name);
    if(school.students_no == INT_MAX) { errno = ERANGE; return 0; }
    if(!(students = realloc(school.students,
        sizeof *school.students * (school.students_no + 1)))) return 0;
    school.students = students;
    s = school.students + school.students_no;
    s->id = school.students_no;
    s->name = name;
    s->takes_head = 0;
    school.students_no++;
    printf("%s is assigned id %d.\n", s->name, s->id);
    return s;
}

/* May output in a static buffer. */
static const char *student_to_string(const int id) {
    struct Student *const student = lookup_student(id);
    static char str[256] = ""; /* Static buffer. */
    if(!student) { sprintf(str, "<student id %d>", id); return str; }
    return student->name;
}

static struct Takes *lookup_takes(const int student_id, const int subject_id) {
    const struct Student *const student = lookup_student(student_id);
    struct Takes *t;
    if(!student) return 0;
    for(t = student->takes_head; t && t->subject_id != subject_id; t = t->next_student);
    return t;
}

static struct Takes *add_takes(const int student_id, const int subject_id) {
    struct Subject *const subject = lookup_subject(subject_id);
    struct Student *const student = lookup_student(student_id);
    struct Takes *t = lookup_takes(student_id, subject_id);
    printf("%s enrols in %s.\n", student_to_string(student_id),
        subject_to_string(subject_id));
    /* Already have it. */
    if(t) return t;
    /* Or else make a new. */
    if(!subject || !student) { errno = EDOM; return 0; }
    if(!(t = malloc(sizeof *t))) return 0;
    t->subject_id = subject_id;
    t->student_id = student_id;
    t->next_subject = subject->takes_head, subject->takes_head = t;
    t->next_student = student->takes_head, student->takes_head = t;
    return t;
}

static void print_subject(const int subject_id) {
    struct Subject *const subject = lookup_subject(subject_id);
    struct Takes *t;
    printf("_Subject: %s._\n", subject_to_string(subject_id));
    if(!subject) return;
    for(t = subject->takes_head; t; t = t->next_subject)
        printf("%s takes %s.\n", student_to_string(t->student_id),
        subject_to_string(t->subject_id));
}

static void print_student(const int student_id) {
    struct Student *const student = lookup_student(student_id);
    struct Takes *t;
    printf("_Student: %s._\n", student_to_string(student_id));
    if(!student) return;
    for(t = student->takes_head; t; t = t->next_student)
        printf("%s takes %s.\n", student_to_string(t->student_id),
            subject_to_string(t->subject_id));
}

int main(void) {
    const char *why = 0;
    do { /* Try. */
        struct Subject *subject;
        struct Student *student;
        int herbology_id, defense_id, potions_id;
        int hermione_id, ron_id, harry_id;

        why = "Herbology";
        if(!(subject = add_subject(why))) break;
        herbology_id = subject->id;
        why = "Defense";
        if(!(subject = add_subject(why))) break;
        defense_id = subject->id;
        why = "Potions";
        if(!(subject = add_subject(why))) break;
        potions_id = subject->id;
        why = "Hermione";
        if(!(student = add_student(why))) break;
        hermione_id = student->id;
        why = "Ron";
        if(!(student = add_student(why))) break;
        ron_id = student->id;
        why = "Harry";
        if(!(student = add_student(why))) break;
        harry_id = student->id;
        why = "enrol";
        if(!add_takes(hermione_id, defense_id)
            || !add_takes(hermione_id, potions_id)
            || !add_takes(hermione_id, herbology_id)
            || !add_takes(ron_id, herbology_id)
            || !add_takes(harry_id, potions_id)) break;
        print_subject(herbology_id);
        print_subject(defense_id);
        print_subject(potions_id);
        print_student(hermione_id);
        why = 0;
    } while(0); if(why) perror(why); /* Catch. */
    /* fixme: free memory in 'final' block. Remember to free Takes. */
    return why ? EXIT_FAILURE : EXIT_SUCCESS;
}
#包括/*退出uuurealloc*/
#包括/*INT\u MAX*/
#包括/*错误号*/
#包括/*perror printf*/
#包括/*断言*/
结构主题{
int id;/*主键*/
常量字符*名称;
结构取*取头;
};
结构学生{
int id;/*主键*/
常量字符*名称;
结构取*取头;
};
/*(弱)结合实体*/
结构采取{
int subject_id,student_id;/*复合键*/
struct接受*下一个课程,*下一个学生;
};
静态结构学派{
结构主题*主题;
国际科目(无);
结构学生*学生;
国际学生联合会;
}学校;
静态结构主题*查找主题(const int id){
如果(id>=school.subjects\u no)返回0;
返回学校。科目+id;
}
静态结构主题*添加主题(常量字符*名称){
结构主题*subjects,*s;
断言(名称);
if(school.subjects_no==INT_MAX){errno=ERANGE;返回0;}
/*修正:realloc速度慢;例如,容量加倍*/
如果(!(科目=realloc(学校科目,
sizeof*school.subjects*(school.subjects_no+1)))返回0;
school.subjects=科目;
s=school.subjects+school.subjects\u no;
s->id=学校。科目\u编号;
s->name=name;
s->takes_head=0;
学校.科目_no++;
返回s;
}
/*可以在静态缓冲区中输出*/
静态常量字符*主语到字符串(常量整数id){
结构主题*常量主题=查找主题(id);
静态字符str[256]=“”;/*静态缓冲区*/
if(!subject){sprintf(str,“,id);返回str;}
返回主题->名称;
}
静态结构学生*查找学生(const int id){
如果(id>=school.students\u no)返回0;
返回学校。学生+身份证;
}
静态结构学生*添加学生(常量字符*名称){
结构学生*Student,*s;
断言(名称);
如果(school.students_no==INT_MAX){errno=ERANGE;返回0;}
如果(!(学生=realloc(school.students,
sizeof*school.students*(school.students_no+1)))返回0;
school.student=学生;
s=school.students+school.students\u no;
s->id=school.students\u no;
s->name=name;
s->takes_head=0;
学校。学生们;
printf(“%s被分配了id%d。\n”,s->name,s->id);
返回s;
}
/*可以在静态缓冲区中输出*/
静态常量字符*学生到字符串(常量整数id){
struct Student*const Student=lookup\u Student(id);
静态字符str[256]=“”;/*静态缓冲区*/
如果(!student){sprintf(str,“,id);返回str;}
返回学生->姓名;
}
静态结构获取*查找获取(常量int学生id、常量int主题id){
const struct Student*const Student=查找学生(学生id);
struct取*t;
如果(!student)返回0;
for(t=student->takes\u head;t&&t->subject\u id!=subject\u id;t=t->next\u student);
返回t;
}
静态结构获取*添加获取(常量int学生id、常量int主题id){
结构主题*常量主题=查找主题(主题id);
结构学生*常量学生=查找学生(学生id);
struct Takes*t=lookup\u Takes(学生id、科目id);
printf(“%s在%s中注册。\n”,学生对学生字符串(学生id),
subject_to_字符串(subject_id));
/*已经有了*/
如果(t)返回t;
/*或者做一个新的*/
如果(!subject | |!student){errno=EDOM;返回0;}
如果(!(t=malloc(sizeof*t)),则返回0;
t->subject\u id=subject\u id;
t->student\u id=student\u id;
t->next\u subject=subject->takes\u head,subject->takes\u head=t;
t->next_student=student->takes_head,student->takes_head=t;
返回t;
}
静态无效打印主题(const int主题id){
结构主题*常量主题=查找主题(主题id);
struct取*t;
printf(“\u主题:%s.\u\n”,主题到字符串(主题id));
如果(!主题)返回;
for(t=subject->takes\u head;t;t=t->next\u subject)
printf(“%s接受%s.\n”,学生对学生字符串(t->学生id),
主题到字符串(t->主题id);
}
静态无效打印学生(常量int学生id){
结构学生*常量学生=查找学生(学生id);
struct取*t;
printf(“\u学生:%s.\u\n”,学生到字符串(学生id));
如果(!学生)返回;
for(t=student->takes\u head;t;t=t->next\u student)
printf(“%s接受%s.\n”,学生对学生字符串(t->学生id),
主题到字符串(t->主题id);
}
内部主(空){
常量字符*为什么=0;
试试看*/
结构主语*主语;
结构学生*Student;
int药草学id、防御id、药剂id;
赫敏,罗恩,哈利;
为什么=“草本学”;
如果(!(主题=添加主题(为什么))中断;
草药学=主题->id;
为什么“防卫”;
如果(!(主题=添加主题(为什么))中断;
防御id=主体->身份;
为什么=“药剂”;
如果(!(主题=添加主题(为什么))中断;
药剂\u id=主体->标识;
为什么=“赫敏”;
如果(!(学生=添加学生(为什么))中断;
赫米