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のブロックみたいな感じで使えます。超便利そう。
まとめ
- 最初はvoid *型で作ってたんですが、Rubyに合わせてみました。
- 線形リストでは物足りなくなってくると思うので、今後はこのライブラリを発展させつつ使っていく予定です。