汎用的な連結リストを構築する

C言語ポインタ完全制覇 5-2-4

連結リストは得てして同じような実装を量産する。

そこで実際に持つべきデータをvoidポインタにしておくことで何でも格納可能な連結リストを実現できる。

ただし何でも入ってしまうが故、何が入ってるのかわかりにくくなるので慎重に扱わなければならない。

ということで実装してみます。

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

typedef struct {
    char *data;
} DATA;

typedef struct LIST {
    void *object;
    struct LIST *next;
    struct LIST *prev;
} LIST;

LIST *create_list(void *object) {
    LIST *p;
    p = (LIST *)malloc(sizeof(LIST));
    if ( p == NULL ) return NULL;
    p->object = object;
    p->next = p->prev = p;
    return p;
}

LIST *add_list(LIST *p,void *object) {
    LIST *add;
    
    if ( p == NULL ) {
        return create_list(object);
    }
    
    add = create_list(object);
    add->object = object;
    add->next = p->next;
    add->prev = p;
    p->next = add;
    
    return p;
}

void show_list(LIST *p,void (*show)(void *)) {
    LIST *s = p;
    
    do {
        (*show)(p->object);
        p = p->next;
    } while (p != s);
}

DATA *create_data(char *str) {
    DATA *p;
    p = (DATA *)malloc(sizeof(DATA));
    if ( p == NULL ) return NULL;
    p->data = _strdup(str);
    return p;
}

void show_data(void *object) {
    DATA *data = (DATA *)object;
    
    printf("%s\n",data->data);
}

int main (void) {
    LIST *p = NULL;
    int i;
    char *word[] = {
        "aaa",
        "bbb",
        "ccc",
    };
    
    
    for(i=0;i<3;i++){
        p = add_list(p,create_data(word[i]));
    }
    
    show_list(p,show_data);
    
    return 0;
}
$ main
aaa
bbb
ccc

LIST型と、create_list、add_list、show_listは汎用的な連結リストとなっています。

保持しているのはvoidポインタなので何でもいれれます。とりあえず例としてDATA型のデータを入れています。

便利ですね。