線形リスト構造(2)

Copyright(C) 14May2003 coskx TNCT

多くの同じ型の変数を扱う場合,配列が使われることが多い。プログラミングの時点で,使用する配列の大きさ(要素数)がわかっている場合は静的な配列を使う。
int array[1024]; /*静的な配列の例*/

しかし,プログラミングの時点で配列の大きさがわからない場合は,配列の動的確保の手法があった。しかし,この方法でも,プログラムが起動した直後に配列の大きさが決まらなければ,配列を確保することができない。たとえば人の名前を登録する場合,何人で終わるか見当もつかないことがある。あらかじめ1000人ぐらいを予想してプログラム起動時に1000人分の配列を作っても,途中で不足してしまうこともある。

さて,このように,プログラムの実行が進むにつれて,保存すべきデータ量が増えてゆくときには線形リスト構造というデータ保存の形式がある。線形リスト構造では1データの登録時に1要素を確保するという手法をとる。しかも新たな要素が確保された(作られた)時には新しい要素のアドレスを,直前の要素が覚えているようにする。
このような機能を持つ要素は次のような構造体となる。(ここでは登録データ用の変数は1つだが,複数あってもよい)

線形リスト構造を作る構造体

構造体の要素1

登録データ用の変数

構造体の要素2

次のアドレスをしまうためのポインタ変数

1.線形リスト構造にカタカナ名前を登録し,表示後,全削除する例
  (ポインタのポインタを使って登録関数をスマートに)

線形リスト構造に,「ハリー・ポッター」「ロン・ウィーズリー」「ハーマイオニー・グレンジャー」の3つのカタカナ名前を登録する。

登録用の線形リスト構造をつくる構造体は次のようになる。

名前の線形リスト構造を作る構造体 list_t

構造体の要素1

登録データ用の文字列変数(char型配列)

構造体の要素2

次のアドレスをしまうための「list_tを指すポインタ変数」

最初の3つのデータを登録する様子は次のようになればよい。

(1)初めの状態(データが1つも入っていない状態)

元締めとなる「list_tを指すポインタ変数」 namelist

値(アドレス)

NULL(無効)

(2)1つ目のデータ(「ハリー・ポッター」)が登録された状態

元締めとなるポインタ変数 namelist

値(アドレス)

アドレスa

「アドレスa」に確保された
名前のないlist_t構造体

値(登録データ)

「ハリー・ポッター」

値(次のアドレス)

NULL(無効)

(3)2つ目のデータ(「ロン・ウィーズリー」)が登録された状態

元締めとなるポインタ変数 namelist

値(アドレス)

アドレスa

「アドレスa」に確保された
名前のないlist_t構造体

値(登録データ)

「ハリー・ポッター」

値(次のアドレス)

アドレスb

「アドレスb」に確保された
名前のないlist_t構造体

値(登録データ)

「ロン・ウィーズリー」

値(次のアドレス)

NULL(無効)

(4)3つ目のデータ(「ハーマイオニー・グレンジャー」)が登録された状態

元締めとなるポインタ変数 namelist

値(アドレス)

アドレスa

「アドレスa」に確保された
名前のないlist_t構造体

値(登録データ)

「ハリー・ポッター」

値(次のアドレス)

アドレスb

「アドレスb」に確保された
名前のないlist_t構造体

値(登録データ)

「ロン・ウィーズリー」

値(次のアドレス)

アドレスc

「アドレスc」に確保された
名前のないlist_t構造体

値(登録データ)

「ハーマイオニー・
グレンジャー」

値(次のアドレス)

NULL(無効)

このように,データ保存用の構造体は,データを格納する変数と,次の構造体が確保された時のアドレスを保存するポインタ変数からできている。
データが登録された構造体はこのポインタ変数によってつながっており,最後に登録された構造体のポインタ変数には必ず「NULL」が入るようになっている。

サンプルプログラムを次に示す。登録の様子を見るために,データ未登録状態の様子,データを登録するたびにどのようにリスト構造ができているかを見せまている。この見せるからくりは,void printListStructure(void)である。

関数registerName()中に list_t **ptrptr という「ポインタのポインタ」が出てくるが,これは,『「現在着目中のリスト要素」をさしているアドレス』を格納しているポインタ変数のアドレスを格納する「ポインタのポインタ変数」である。

liststructure.c

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

typedef struct list_type {
    char name[32];
    struct list_type *next;
} list_t;

list_t *namelist=NULL;

/*名前の登録*/
void registerName(char *name)
{
    list_t *newptr,**ptrptr=&namelist;
    while (*ptrptr!=NULL) {
        ptrptr=&((*ptrptr)->next);
    }
    newptr=(list_t *)malloc(sizeof(list_t));
    strcpy(newptr->name,name);
    newptr->next=NULL;
    *ptrptr=newptr;
#ifdef debug
    printf("got [%p] and saved it to [%p]\n",newptr,ptrptr);
#endif
}

/*登録済データ数の読み出し*/
int getNumber(void)
{
    int num=0;
    list_t *ptr=namelist;
    while (ptr!=NULL) {
        ptr=ptr->next;
        num++;
    }
    return num;
}

/*登録済データの指定番号の文字列データの取り出し*/
/*buffはデータ取得の受け入れ場所*/
/*numberは指定番号 0から数える*/
void getName(char *buff,int number)
{
    int i=0;
    list_t *ptr=namelist;
    strcpy(buff,"");
    while (ptr!=NULL) {
        if (i==number) {
            strcpy(buff,ptr->name);
            break;
        }
        ptr=ptr->next;
        i++;
    }
}

/*List構造の解放*/
void closeList(void)
{
    list_t *ptr=namelist,*ptr1;
    while (ptr!=NULL) {
        ptr1=ptr;
        ptr=ptr->next;
        free(ptr1);
#ifdef debug
        printf("freed [%p]\n",ptr1);
#endif
    }
    namelist=NULL;
}

/*リスト構造の利用開始*/
void openList(void)
{
    closeList();
}

#ifdef debug
void printListStructure(void)
{
    static counter=0;
    list_t *node;
    printf("** printListStructure (debug %d) **\n",++counter);
    printf("&namelist(root)=%p\n",&namelist);
    printf("namelist(root) =%p\n",namelist);
    node=namelist;
    while (node!=NULL) {
        printf("&node = %p\n",node);
        printf("   node.name = [%s]\n",node->name);
        printf("   node.next = [%p]\n",node->next);
        node=node->next;
    }
    printf("\n");
}
#endif

int main()
{
    int number,i;
    char tmp[128];
    openList(); /*リスト構造の利用開始*/
#ifdef debug
    printListStructure();
#endif
    registerName("ハリー・ポッター"); /*名前の登録*/
#ifdef debug
    printListStructure();
#endif
    registerName("ロン・ウィーズリー"); /*名前の登録*/
#ifdef debug
    printListStructure();
#endif
    registerName("ハーマイオニー・グレンジャー"); /*名前の登録*/
#ifdef debug
    printListStructure();
#endif
    number=getNumber(); /*登録済データ数の取得*/
    printf("%d\n",number);
    for (i=0;i<number;i++) {
        getName(tmp,i); /*番号指定でデータの取得*/
        puts(tmp);
    }
    closeList(); /*List構造の解放*/
    number=getNumber();
    printf("%d\n",number);
#ifdef debug
    printListStructure();
#endif
    return 0;
}

実行結果
デバッグモード(#define debugが有効な時)
(「#ifdef debug」と「#endif」の間も実行する)

** printListStructure (debug 1) **
&namelist(root)=0040D000
namelist(root) =00000000

got [00373148] and saved it to [0040D000]
** printListStructure (debug 2) **
&namelist(root)=0040D000
namelist(root) =00373148
&node = 00373148
   node.name = [ハリー・ポッター]
   node.next = [00000000]

got [00373178] and saved it to [00373168]
** printListStructure (debug 3) **
&namelist(root)=0040D000
namelist(root) =00373148
&node = 00373148
   node.name = [ハリー・ポッター]
   node.next = [00373178]
&node = 00373178
   node.name = [ロン・ウィーズリー]
   node.next = [00000000]

got [003731A8] and saved it to [00373198]
** printListStructure (debug 4) **
&namelist(root)=0040D000
namelist(root) =00373148
&node = 00373148
   node.name = [ハリー・ポッター]
   node.next = [00373178]
&node = 00373178
   node.name = [ロン・ウィーズリー]
   node.next = [003731A8]
&node = 003731A8
   node.name = [ハーマイオニー・グレンジャー]
   node.next = [00000000]

3
ハリー・ポッター
ロン・ウィーズリー
ハーマイオニー・グレンジャー
freed [00373148]
freed [00373178]
freed [003731A8]
0
** printListStructure (debug 5) **
&namelist(root)=0040D000
namelist(root) =00000000

実行結果
利用モード(「#define debug」を「/*#define debug*/」にして無効にした場合)
(「#ifdef debug」と「#endif」の間は実行されない(実はコンパイルもされない))
3
ハリー・ポッター
ロン・ウィーズリー
ハーマイオニー・グレンジャー
0

デバッグモードで実行した結果,3つのデータが登録されてゆく状態が次のようにわかる。

(1)データ未登録状態(** printListStructure (debug 1) **)

元締めとなるポインタ変数 namelist
この変数のアドレス:0040D000

値(アドレス)

NULL(表示では00000000)

(2)「ハリー・ポッター」が登録された状態(** printListStructure (debug 2) **)

元締めとなるポインタ変数 namelist
この変数のアドレス:0040D000

値(アドレス)

00373148

00373148に確保された
名前のないlist_t構造体

値(登録データ)

「ハリー・ポッター」

値(次のアドレス)

NULL(表示では00000000)

(3)「ロン・ウィーズリー」が登録された状態(** printListStructure (debug 3) **)

元締めとなるポインタ変数 namelist
この変数のアドレス:0040D000

値(アドレス)

00373148

00373148に確保された
名前のないlist_t構造体

値(登録データ)

「ハリー・ポッター」

値(次のアドレス)

00373178

00373178に確保された
名前のないlist_t構造体

値(登録データ)

「ロン・ウィーズリー」

値(次のアドレス)

NULL(表示では00000000)

(4)「ハーマイオニー・グレンジャー」が登録された状態(** printListStructure (debug 4) **)

元締めとなるポインタ変数 namelist
この変数のアドレス:0040D000

値(アドレス)

00373148

00373148に確保された
名前のないlist_t構造体

値(登録データ)

「ハリー・ポッター」

値(次のアドレス)

00373178

00373178に確保された
名前のないlist_t構造体

値(登録データ)

「ロン・ウィーズリー」

値(次のアドレス)

003731A8

003731A8に確保された
名前のないlist_t構造体

値(登録データ)

「ハーマイオニー・
グレンジャー」

値(次のアドレス)

NULL(表示では00000000)

2.線形リスト構造にカタカナ名前を辞書順に登録し,表示後,全削除する例

名前を辞書順に登録してみよう。リストの中間に新しいデータを登録する場合も生ずる。
登録する名前は「ハリー・ポッター」「ロン・ウィーズリー」「ハーマイオニー・グレンジャー」「ルビウス・ハグリッド」「アルバス・ダンブルドア」で,この順に与えるものとする。ただし,出来上がったリストでは次の順に並んでいるようにする。
アルバス・ダンブルドア
ハーマイオニー・グレンジャー
ハリー・ポッター
ルビウス・ハグリッド
ロン・ウィーズリー

状況を想定すると,最初の2つの登録(「ハリー・ポッター」「ロン・ウィーズリー」)は先の例のとおりに行なわれる。次に「ハーマイオニー・グレンジャー」を登録しようとすると先頭に割り込ませることになる。(「ー」は「リ」より前になる)そこで次のような作業になるであろう。(なおアドレスが書いてあるが,実は実行結果を見ながら書いたものである。実行前にどこのアドレスでこれらの作業が行なわれるか想定するのは不可能である。)

作業前

元締めとなるポインタ変数 namelist
この変数のアドレス:00407A80

値(アドレス)

00410640

00410640に確保された名前のないlist_t構造体

値(登録データ)

「ハリー・ポッター」

値(次のアドレス)

00410610

00410610に確保された名前のないlist_t構造体

値(登録データ)

「ロン・ウィーズリー」

値(次のアドレス)

NULL(表示では00000000)

この位置に
「ハーマイオニー・グレンジャー」
を追加

作業後

元締めとなるポインタ変数 namelist
この変数のアドレス:00407A80

値(アドレス)

004105E0

004105E0に確保された
名前のないlist_t構造体

値(登録データ)

「ハーマイオニー・
グレンジャー」

値(次のアドレス)

00410640

00410640に確保された
名前のないlist_t構造体

値(登録データ)

「ハリー・ポッター」

値(次のアドレス)

00410610

00410610に確保された
名前のないlist_t構造体

値(登録データ)

「ロン・ウィーズリー」

値(次のアドレス)

NULL
(表示では00000000)

そして,その次の「ルビウス・ハグリッド」の登録時には,「ハリー・ポッター」と「ロン・ウィーズリー」の間に登録することになるので,つぎの作業が想定される。

作業前

元締めとなるポインタ変数 namelist
この変数のアドレス:00407A80

値(アドレス)

004105E0

004105E0に確保された
名前のないlist_t構造体

値(登録データ)

「ハーマイオニー・
グレンジャー」

値(次のアドレス)

00410640

00410640に確保された
名前のないlist_t構造体

値(登録データ)

「ハリー・ポッター」

値(次のアドレス)

00410610

00410610に確保された
名前のないlist_t構造体

値(登録データ)

「ロン・ウィーズリー」

値(次のアドレス)

NULL
(表示では00000000)

この位置に
「ルビウス・ハグリッド」
を追加

作業後

元締めとなるポインタ変数 namelist
この変数のアドレス:00407A80

値(アドレス)

004105E0

004105E0に確保された
名前のないlist_t構造体

値(登録データ)

「ハーマイオニー・
グレンジャー」

値(次のアドレス)

00410640

00410640に確保された
名前のないlist_t構造体

値(登録データ)

「ハリー・ポッター」

値(次のアドレス)

004105B0

004105B0に確保された
名前のないlist_t構造体

値(登録データ)

「ルビウス・ハグリッド」

値(次のアドレス)

00410610

00410610に確保された名前のないlist_t構造体

値(登録データ)

「ロン・ウィーズリー」

値(次のアドレス)

NULL
(表示では00000000)

次のプログラムを追跡し,データの登録の様子を確認せよ。

関数registerNameSorted()中に list_t **ptrptr という「ポインタのポインタ」が出てくるが,これは,『「現在着目中のリスト要素」をさしているアドレス』を格納しているポインタ変数のアドレスを格納する「ポインタのポインタ変数」である。

リストに名前を辞書順に登録する

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

typedef struct list_type {
    char name[32];
    struct list_type *next;
} list_t;

list_t *namelist=NULL;

/*辞書順に並べながら名前の登録*/
void registerNameSorted(char *name)
{
    list_t *newptr,**ptrptr=&namelist;
    int judge;/*文字列の辞書順の判定*/
    if (*ptrptr!=NULL) judge=strcmp((*ptrptr)->name,name);
    while (*ptrptr!=NULL&&judge<0) {
        ptrptr=&((*ptrptr)->next);
        if (*ptrptr!=NULL) judge=strcmp((*ptrptr)->name,name);
    }
    newptr=(list_t *)malloc(sizeof(list_t));
    strcpy(newptr->name,name);
    newptr->next=*ptrptr;
    *ptrptr=newptr;
#ifdef debug
    printf("accepted [%s] \n",name);
    printf("got [%p] and saved it to [%p] and linked to [%p]\n",newptr,ptrptr,newptr->next);
#endif
}

/*登録済データ数の読み出し*/
int getNumber(void)
{
    int num=0;
    list_t *ptr=namelist;
    while (ptr!=NULL) {
        ptr=ptr->next;
        num++;
    }
    return num;
}

/*登録済データの指定番号の文字列データの取り出し*/
/*buffはデータ取得の受け入れ場所*/
/*numberは指定番号 0から数える*/
void getName(char *buff,int number)
{
    int i=0;
    list_t *ptr=namelist;
    strcpy(buff,"");
    while (ptr!=NULL) {
        if (i==number) {
            strcpy(buff,ptr->name);
            break;
        }
        ptr=ptr->next;
        i++;
    }
}

/*List構造の解放*/
void closeList(void)
{
    list_t *ptr=namelist,*ptr1;
    while (ptr!=NULL) {
        ptr1=ptr;
        ptr=ptr->next;
        free(ptr1);
#ifdef debug
        printf("released [%p]\n",ptr1);
#endif
    }
    namelist=NULL;
}

/*リスト構造の利用開始*/
void openList(void)
{
    closeList();
}

#ifdef debug
void printListStructure(void)
{
    static counter=0;
    list_t *node;
    printf("** printListStructure (debug %d) **\n",++counter);
    printf("&namelist(root)=%p\n",&namelist);
    printf("namelist(root) =%p\n",namelist);
    node=namelist;
    while (node!=NULL) {
        printf("&node = %p\n",node);
        printf("   node.name = [%s]\n",node->name);
        printf("   node.next = [%p]\n",node->next);
        node=node->next;
    }
    printf("\n");
}
#endif

int main()
{
    int number,i;
    char tmp[128];
    openList(); /*リスト構造の利用開始*/
#ifdef debug
    printListStructure();
#endif
    registerNameSorted("ハリー・ポッター"); /*名前の登録*/
#ifdef debug
    printListStructure();
#endif
    registerNameSorted("ロン・ウィーズリー"); /*名前の登録*/
#ifdef debug
    printListStructure();
#endif
    registerNameSorted("ハーマイオニー・グレンジャー"); /*名前の登録*/
#ifdef debug
    printListStructure();
#endif
    registerNameSorted("ルビウス・ハグリッド"); /*名前の登録*/
#ifdef debug
    printListStructure();
#endif
    registerNameSorted("アルバス・ダンブルドア"); /*名前の登録*/
#ifdef debug
    printListStructure();
#endif
    number=getNumber(); /*登録済データ数の取得*/
    printf("%d\n",number);
    for (i=0;i<number;i++) {
        getName(tmp,i); /*番号指定でデータの取得*/
        puts(tmp);
    }
    closeList(); /*List構造の解放*/
    number=getNumber();
    printf("%d\n",number);
    return 0;
}

実行結果
デバッグモード(#define debugが有効な時)
(「#ifdef debug」と「#endif」の間も実行する)

** printListStructure (debug 1) **
&namelist(root)=00407A80
namelist(root) =00000000

accepted [ハリー・ポッター]
got [00410640] and saved it to [00407A80] and linked to [00000000]
** printListStructure (debug 2) **
&namelist(root)=00407A80
namelist(root) =00410640
&node = 00410640
   node.name = [ハリー・ポッター]
   node.next = [00000000]

accepted [ロン・ウィーズリー]
got [00410610] and saved it to [00410660] and linked to [00000000]
** printListStructure (debug 3) **
&namelist(root)=00407A80
namelist(root) =00410640
&node = 00410640
   node.name = [ハリー・ポッター]
   node.next = [00410610]
&node = 00410610
   node.name = [ロン・ウィーズリー]
   node.next = [00000000]

accepted [ハーマイオニー・グレンジャー]
got [004105E0] and saved it to [00407A80] and linked to [00410640]
** printListStructure (debug 4) **
&namelist(root)=00407A80
namelist(root) =004105E0
&node = 004105E0
   node.name = [ハーマイオニー・グレンジャー]
   node.next = [00410640]
&node = 00410640
   node.name = [ハリー・ポッター]
   node.next = [00410610]
&node = 00410610
   node.name = [ロン・ウィーズリー]
   node.next = [00000000]

accepted [ルビウス・ハグリッド]
got [004105B0] and saved it to [00410660] and linked to [00410610]
** printListStructure (debug 5) **
&namelist(root)=00407A80
namelist(root) =004105E0
&node = 004105E0
   node.name = [ハーマイオニー・グレンジャー]
   node.next = [00410640]
&node = 00410640
   node.name = [ハリー・ポッター]
   node.next = [004105B0]
&node = 004105B0
   node.name = [ルビウス・ハグリッド]
   node.next = [00410610]
&node = 00410610
   node.name = [ロン・ウィーズリー]
   node.next = [00000000]

accepted [アルバス・ダンブルドア]
got [00410580] and saved it to [00407A80] and linked to [004105E0]
** printListStructure (debug 6) **
&namelist(root)=00407A80
namelist(root) =00410580
&node = 00410580
   node.name = [アルバス・ダンブルドア]
   node.next = [004105E0]
&node = 004105E0
   node.name = [ハーマイオニー・グレンジャー]
   node.next = [00410640]
&node = 00410640
   node.name = [ハリー・ポッター]
   node.next = [004105B0]
&node = 004105B0
   node.name = [ルビウス・ハグリッド]
   node.next = [00410610]
&node = 00410610
   node.name = [ロン・ウィーズリー]
   node.next = [00000000]

5
アルバス・ダンブルドア
ハーマイオニー・グレンジャー
ハリー・ポッター
ルビウス・ハグリッド
ロン・ウィーズリー
released [00410580]
released [004105E0]
released [00410640]
released [004105B0]
released [00410610]
0

 

3.線形リスト構造の指定場所に登録,指定場所を削除する例

 

線形リスト構造の先頭からN番目の位置に名前を登録する関数registerName()と指定の位置の名前を削除する関数deleteName()を作ります。先頭から3番目に「ichiro」を登録したかったら,registerName(3,"ichiro")というように使います。先頭から5番目の要素を削除したかったらdeleteName(5)のように使います。
ただし,これらの関数では,各要素は0,1,2,3,...と数えます。また要素数が3つしかないのに6番目に登録しようとしたり,10番目を削除使用とした場合は,これらの関数はエラーを表示し,リスト構造への作業は何もしないことにします。

関数registerName(),deleteName()中に list_t **ptrptr という「ポインタのポインタ」が出てくるが,これは,『「現在着目中のリスト要素」をさしているアドレス』を格納しているポインタ変数のアドレスを格納する「ポインタのポインタ変数」である。

liststructure.c

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

typedef struct list_type {
    char name[32];
    struct list_type *next;
} list_t;

list_t *namelist=NULL;

/*先頭からnumber番目に登録(先頭は0番目)*/
void registerName(int number, char *name)
{
    list_t *newptr,**ptrptr=&namelist;
    int count=0;
    while (*ptrptr!=NULL&&count<number) {
        ptrptr=&((*ptrptr)->next);
        count++;
    }
    if (count==number) {
        newptr=(list_t *)malloc(sizeof(list_t));
        strcpy(newptr->name,name);
        newptr->next=*ptrptr;
        *ptrptr=newptr;
#ifdef debug
        printf("accepted [%s] \n",name);
        printf("got [%p] and saved it to [%p] and linked to [%p]\n",newptr,ptrptr,newptr->next);
#endif
    } else {
        printf("**REEOR** %d is out of range\n",number);
    }
}

/*先頭からnumber番目のデータを消去(先頭は0番目)*/
void deleteName(int number)
{
    list_t *delptr,**ptrptr=&namelist;
    int count=0;
    while (*ptrptr!=NULL&&count<number) {
        ptrptr=&((*ptrptr)->next);
        count++;
    }
    if (count==number&&*ptrptr!=NULL) {
        delptr=*ptrptr;
        *ptrptr=delptr->next;
        free(delptr);
#ifdef debug
        printf("accepted [%d] \n",number);
#endif
    } else {
        printf("**REEOR** %d is out of range\n",number);
    }
}

/*登録済データ数の読み出し*/
int getNumber(void)
{
    int num=0;
    list_t *ptr=namelist;
    while (ptr!=NULL) {
        ptr=ptr->next;
        num++;
    }
    return num;
}

/*登録済データの指定番号の文字列データの取り出し*/
/*buffはデータ取得の受け入れ場所*/
/*numberは指定番号 0から数える*/
void getName(char *buff,int number)
{
    int i=0;
    list_t *ptr=namelist;
    strcpy(buff,"");
    while (ptr!=NULL) {
        if (i==number) {
            strcpy(buff,ptr->name);
            break;
        }
        ptr=ptr->next;
        i++;
    }
}

/*List構造の解放*/
void closeList(void)
{
    list_t *ptr=namelist,*ptr1;
    while (ptr!=NULL) {
        ptr1=ptr;
        ptr=ptr->next;
        free(ptr1);
#ifdef debug
        printf("released [%p]\n",ptr1);
#endif
    }
    namelist=NULL;
}

/*リスト構造の利用開始*/
void openList(void)
{
    closeList();
}

#ifdef debug
void printListStructure(void)
{
    static counter=0;
    list_t *node;
    printf("** printListStructure (debug %d) **\n",++counter);
    printf("&namelist(root)=%p\n",&namelist);
    printf("namelist(root) =%p\n",namelist);
    node=namelist;
    while (node!=NULL) {
        printf("&node = %p\n",node);
        printf("   node.name = [%s]\n",node->name);
        printf("   node.next = [%p]\n",node->next);
        node=node->next;
    }
    printf("\n");
}
#endif

int main()
{
    int number,i;
    char tmp[128];
    openList(); /*リスト構造の利用開始*/
#ifdef debug
    printListStructure();
#endif
    registerName(1,"エラーのテストさん"); /*名前の登録 これは失敗する*/
    registerName(0,"ハリー・ポッター"); /*名前の登録*/
#ifdef debug
    printListStructure();
#endif
    registerName(1,"ロン・ウィーズリー"); /*名前の登録*/
#ifdef debug
    printListStructure();
#endif
    registerName(2,"ハーマイオニー・グレンジャー"); /*名前の登録*/
#ifdef debug
    printListStructure();
#endif
    registerName(0,"ルビウス・ハグリッド"); /*名前の登録*/
#ifdef debug
    printListStructure();
#endif
    registerName(0,"アルバス・ダンブルドア"); /*名前の登録*/
    registerName(6,"エラーのテストさん"); /*名前の登録 これは失敗する*/
#ifdef debug
    printListStructure();
#endif
    number=getNumber(); /*登録済データ数の取得*/
    printf("%d\n",number);
    for (i=0;i<number;i++) {
        getName(tmp,i); /*番号指定でデータの取得*/
        puts(tmp);
    }
    deleteName(5); /*これはエラーになることを確認するための作業*/
    number=getNumber(); /*登録済データ数の取得*/
    printf("%d\n",number);
    for (i=0;i<number;i++) {
        getName(tmp,i); /*番号指定でデータの取得*/
        puts(tmp);
    }
    deleteName(4);
    number=getNumber(); /*登録済データ数の取得*/
    printf("%d\n",number);
    for (i=0;i<number;i++) {
        getName(tmp,i); /*番号指定でデータの取得*/
        puts(tmp);
    }
    deleteName(3);
    number=getNumber(); /*登録済データ数の取得*/
    printf("%d\n",number);
    for (i=0;i<number;i++) {
        getName(tmp,i); /*番号指定でデータの取得*/
        puts(tmp);
    }
    deleteName(2);
    number=getNumber(); /*登録済データ数の取得*/
    printf("%d\n",number);
    for (i=0;i<number;i++) {
        getName(tmp,i); /*番号指定でデータの取得*/
        puts(tmp);
    }
    deleteName(1);
    number=getNumber(); /*登録済データ数の取得*/
    printf("%d\n",number);
    for (i=0;i<number;i++) {
        getName(tmp,i); /*番号指定でデータの取得*/
        puts(tmp);
    }
    deleteName(0);
    number=getNumber(); /*登録済データ数の取得*/
    printf("%d\n",number);
    for (i=0;i<number;i++) {
        getName(tmp,i); /*番号指定でデータの取得*/
        puts(tmp);
    }
    deleteName(0); /*これはエラーになることを確認するための作業*/

    closeList(); /*List構造の解放*/
    number=getNumber();
    printf("%d\n",number);
    return 0;
}

実行結果
デバッグモード(#define debugが有効な時)
(「#ifdef debug」と「#endif」の間も実行する)

** printListStructure (debug 1) **
&namelist(root)=00428C3C
namelist(root) =00000000

**REEOR** 1 is out of range
accepted [ハリー・ポッター]
got [00370FE0] and saved it to [00428C3C] and linked to [00000000]
** printListStructure (debug 2) **
&namelist(root)=00428C3C
namelist(root) =00370FE0
&node = 00370FE0
   node.name = [ハリー・ポッター]
   node.next = [00000000]

accepted [ロン・ウィーズリー]
got [00371038] and saved it to [00371000] and linked to [00000000]
** printListStructure (debug 3) **
&namelist(root)=00428C3C
namelist(root) =00370FE0
&node = 00370FE0
   node.name = [ハリー・ポッター]
   node.next = [00371038]
&node = 00371038
   node.name = [ロン・ウィーズリー]
   node.next = [00000000]

accepted [ハーマイオニー・グレンジャー]
got [00371090] and saved it to [00371058] and linked to [00000000]
** printListStructure (debug 4) **
&namelist(root)=00428C3C
namelist(root) =00370FE0
&node = 00370FE0
   node.name = [ハリー・ポッター]
   node.next = [00371038]
&node = 00371038
   node.name = [ロン・ウィーズリー]
   node.next = [00371090]
&node = 00371090
   node.name = [ハーマイオニー・グレンジャー]
   node.next = [00000000]

accepted [ルビウス・ハグリッド]
got [003710E8] and saved it to [00428C3C] and linked to [00370FE0]
** printListStructure (debug 5) **
&namelist(root)=00428C3C
namelist(root) =003710E8
&node = 003710E8
   node.name = [ルビウス・ハグリッド]
   node.next = [00370FE0]
&node = 00370FE0
   node.name = [ハリー・ポッター]
   node.next = [00371038]
&node = 00371038
   node.name = [ロン・ウィーズリー]
   node.next = [00371090]
&node = 00371090
   node.name = [ハーマイオニー・グレンジャー]
   node.next = [00000000]

accepted [アルバス・ダンブルドア]
got [003733D8] and saved it to [00428C3C] and linked to [003710E8]
**REEOR** 6 is out of range
** printListStructure (debug 6) **
&namelist(root)=00428C3C
namelist(root) =003733D8
&node = 003733D8
   node.name = [アルバス・ダンブルドア]
   node.next = [003710E8]
&node = 003710E8
   node.name = [ルビウス・ハグリッド]
   node.next = [00370FE0]
&node = 00370FE0
   node.name = [ハリー・ポッター]
   node.next = [00371038]
&node = 00371038
   node.name = [ロン・ウィーズリー]
   node.next = [00371090]
&node = 00371090
   node.name = [ハーマイオニー・グレンジャー]
   node.next = [00000000]

5
アルバス・ダンブルドア
ルビウス・ハグリッド
ハリー・ポッター
ロン・ウィーズリー
ハーマイオニー・グレンジャー
**REEOR** 5 is out of range
5
アルバス・ダンブルドア
ルビウス・ハグリッド
ハリー・ポッター
ロン・ウィーズリー
ハーマイオニー・グレンジャー
accepted [4]
4
アルバス・ダンブルドア
ルビウス・ハグリッド
ハリー・ポッター
ロン・ウィーズリー
accepted [3]
3
アルバス・ダンブルドア
ルビウス・ハグリッド
ハリー・ポッター
accepted [2]
2
アルバス・ダンブルドア
ルビウス・ハグリッド
accepted [1]
1
アルバス・ダンブルドア
accepted [0]
0
**REEOR** 0 is out of range
0

実行結果
利用モード(「#define debug」を「/*#define debug*/」にして無効にした場合)
(「#ifdef debug」と「#endif」の間は実行されない(実はコンパイルもされない))
**REEOR** 1 is out of range
**REEOR** 6 is out of range
5
アルバス・ダンブルドア
ルビウス・ハグリッド
ハリー・ポッター
ロン・ウィーズリー
ハーマイオニー・グレンジャー
**REEOR** 5 is out of range
5
アルバス・ダンブルドア
ルビウス・ハグリッド
ハリー・ポッター
ロン・ウィーズリー
ハーマイオニー・グレンジャー
4
アルバス・ダンブルドア
ルビウス・ハグリッド
ハリー・ポッター
ロン・ウィーズリー
3
アルバス・ダンブルドア
ルビウス・ハグリッド
ハリー・ポッター
2
アルバス・ダンブルドア
ルビウス・ハグリッド
1
アルバス・ダンブルドア
0
**REEOR** 0 is out of range
0