すがブロ

sugamasaoのhatenablogだよ

リストその2

リストを作ってみた( new と add だけ)

こんな感じの双方向リストを定義して、追加や削除を行う汎用的な関数を作ってみようと思う。
今のところ、追加のみ対応している。
こんな構造体のリストになっているけど、value は void 型のポインタとかにすれば汎用的になるのでは? と思っている。

typedef struct list {
    int value;
    struct list* next;
    struct list* prev;
} intList;

全ソースはこんな感じ

  1 // $Id: list_sample.c 34 2008-05-15 17:07:16Z sugamasao $
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 
  5 typedef struct list {
  6     int value;
  7     struct list* next;
  8     struct list* prev;
  9 } intList;
 10 
 11 /* add */
 12 int addList(intList* list) {
 13     intList* l;
 14     l = (intList*)malloc(sizeof(intList));
 15     if (l == NULL) {
 16         puts("領域確保に失敗したのだ");
 17         return -1;
 18     }
 19 
 20     list->next = l;
 21     l->prev = list;
 22     l->next = NULL;
 23     return 0;
 24 }
 25 
 26 /* new */
 27 int intListNew(intList** list, int size)
 28 {
 29     int i = 0;
 30     intList *tmp;
 31 
 32     if(size < 1) {
 33         puts("構造体の生成はしないのだ");
 34         return 1;
 35     }
 36 
 37     *list = (intList*)malloc(sizeof(intList));
 38     if (list == NULL) {
 39         puts("メモリ確保失敗なのだ");
 40         return 1;
 41     }
 42     (*list)->next = NULL;
 43     (*list)->prev = NULL;
 44 
 45     /* 先頭以降のリストを生成する */
 46     tmp = *list;
 47     for(i = 1; i < size; i++) {
 48         addList(tmp);
 49         tmp = tmp->next;
 50     }
 51 
 52     return 0;
 53 }
 54 
 55 /* main */
 56 int main(void) {
 57     intList* list; // リストを保持するポインタ
 58 
 59     intListNew(&list, 3);
 60 
 61     /* お試し:値を代入してみる */
 62     {
 63         int i = 0;
 64         intList* tmp = list; // リストを保持するポインタ
 65         for(i = 0; i < 3; i++) {
 66             tmp->value = 10+i;
 67             tmp = tmp->next;
 68         }
 69     }
 70     /* お試し:取得した値を表示する */
 71     {
 72         intList* tmp = list; // リストを保持するポインタ
 73         int i;
 74         for(i = 0; i < 3; i++) {
 75             printf("list[%d] = %d\n", i, tmp->value);
 76             tmp = tmp->next;
 77         }
 78     }
 79 
 80     return 0;
 81 }
 82 

ちなみに、実行するとこんな感じ。

sugamasao% gcc -Wall list_sample.c && ./a.out [/Users/sugamasao/dev_work/trunk/lang/c/list_sample]
list[0] = 10
list[1] = 11
list[2] = 12

とりあえず、今思いついている事リスト

  1. malloc は一カ所の関数にできるんじゃね?
  2. add は引数にvaleuに対する初期値を入れるといい感じじゃね?
  3. いやいや、そうすると関数が型に束縛されちゃうなー。int しか使えない、とか char だけ、とかだとイマイチありがたみがないし。
  4. あー、ということはここもなんらかのポインタにすれば良いか?
  5. 一応双方向リストということだけど、値の削除時くらいしか prev の使いどころを思いつかない。
  6. うーん、よくよく考えると削除時とか、値をキーにしたい場合、value の型が無いと走査できないのでは。
  7. 使う側で削除する list のポインタを貰うのは・・・ちょっと使い勝手が悪い感じがするが。そうする方がライブラリ側は楽できるか。
  8. このままだと、list 内の検索(走査)は無理っぽいか(value の型を汎用的にすると)
  9. 配列みたいに、5番目、とかで先頭から5番目の要素のアドレスが帰ってくるとかあると結構便利か。

というわけで

あまりに奥が深くて死にたくなりますね!