K&Rを読もう(4) 番外 線形リスト作り。

リストが無いと死んでしまいそうなので、線形リスト作りました。

汎用性を持たせるためにVALUE型にキャストして使うというRubyのネタをパクってみました。

list.h

まずはヘッダ。

typedef unsigned long VALUE;

struct list_struct {
    VALUE data;
    struct list_struct *next;
};
typedef struct list_struct List;

List *new_list(void);
void  delete_list(List *list);
List *push_list(List *list, VALUE data);
void *each_list(List *list, void (*f)(VALUE));

VALUE data;がポイント。キャストして使います。

list.c

本体でっす。

#include <stdlib.h>

#include "list.h"

static List *alloc_list(void);

static List *alloc_list(void)
{
    List *list = (List *) malloc(sizeof (List));
    if (list == NULL) {
        perror("malloc(3)");
        exit(EXIT_FAILURE);
    }
    return list;
}

List *new_list(void)
{
    List *list = alloc_list();
    list->next = NULL;
    return list;
}

void delete_list(List *list)
{
    List *tmp;
    while (list) {
        tmp = list;
        list = list->next;
        free(tmp);
    }
    free(list);
}

List *push_list(List *list, VALUE data)
{
    List *next = alloc_list();
    next->data = data;
    next->next = list;
    return next;
}

void *each_list(List *list, void (*f)(VALUE))
{
    for (;list->next != NULL;list = list->next)
        f(list->data);
}

リストのfreeは案外大変。

popは当分使わないので、代わりにeachを付けました。でも、値の変更は出来ません。

list_test.c

テスト用。

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

#include "list.h"

void print(VALUE data)
{
    printf("%d ", (int) data);
}

int main(void)
{
    List *list = new_list();

    list = push_list(list, (VALUE) 1);
    list = push_list(list, (VALUE) 2);
    list = push_list(list, (VALUE) 3);

    each_list(list, print);
    
    delete_list(list);

    exit(EXIT_SUCCESS);
}

キャストしてリストに挿入してます。取り出すときに、intに戻します。

今のところ型の管理は手動です(汗

each_listはRubyのブロックみたいな感じで使えます。超便利そう。

コンパイル&テスト

早速テスト。

% gcc -Wextra -o list_test list.c list_test.c
% ./list_test
3 2 1 

each_listイイネ!!

まとめ

  • 最初はvoid *型で作ってたんですが、Rubyに合わせてみました。
  • 線形リストでは物足りなくなってくると思うので、今後はこのライブラリを発展させつつ使っていく予定です。

参考

  • ふつうのLinuxプログラミング 16章
    • 線形リストのfreeが参考になりました。
  • RHG
    • 落ちてるようなので、後でリンク張る。

青木さんありがとう(涙