自己参照的構造体

デ−タ記憶用ブロックを複数個用意し,それぞれのブロックをポインタを用いて鎖状に連結した記憶構造を「リスト構造」と呼び, コンピュ−タにおけるデ−タ処理の実現手法の一つとして重要な概念である.

このリスト構造を実現するには,一つのデ−タ記憶ブロックを一つの構造体を用いて表現する.例えば,整数のリスト(順列)を表現するには,

struct node_struct {

int data;

struct node_struct *next;

};

typedef struct node_struct node;

といった構造体をポインタで結びつけて用いる.

動的メモリ割付け

プログラム中で構造体型の変数を以下のように宣言した場合,コンパイラによって自動的にその構造体のための記憶領域は確保される.

node a_node;

これに対し,予め用意されたポインタ変数を用いて,必要になった時点で追加生成した構造体のデータを指し示したいような場合を考える. 以下のようにポインタ変数を宣言しただけでは,ポインタ変数のためのメモリ領域は用意されるが,

node *b_node_ptr;

このポインタ変数で指し示される対象となる構造体データを格納するためのメモリ領域は,このままでは確保されない. C言語の場合,プログラムの実行中に新しいデ−タ記憶領域が必要になった場合(例えば新しい構造体が一つ必要になった等),malloc関数を用いてメモリ領域を確保する. これは動的メモリ割り付けと呼ばれる.例えば,上記のnode構造体のデ−タが新たに必要になったときは,

b_node_ptr = (node *) malloc(sizeof(node));

というように行う.

ここで,malloc関数は引数で与えられた整数分のバイト数の新しいメモリ領域を確保して,その先頭ポインタを *char (char型ポインタ)で返す. また,sizeof関数は引数で与えられたデ−タ型に必要なメモリサイズをint値で返す関数である.

逆に,不要になったデ−タ領域(構造体など)は,必ず明示的に解放しないとメモリが無駄に消費されてしまう.メモリを解放して有効に再利用できるようにするにはfree()関数を用いる.

free(b_node_ptr);

尚,malloc関数及びfree関数を用いるときは,プログラムの先頭部分に,

#include <stdlib.h>

を付け加えておかねばならない.

注意:

動的なメモリ割付けと解放を繰り返す場合,特に不要になったデ−タ領域の解放を忘れた場合,その不要なデータへのポインタ情報をポインタ変数への代入などにより失ってしまうと, そのメモリ領域がいつまでも解放されないためにプログラムの利用しているメモリが徐々に肥大し,最悪の場合,コンピュ−タのメモリを使い尽くすという間違い(バグ)が発生する. この問題をメモリ・リ−ク(漏れ)と呼び,極めて直しにくい厄介なバグとなるので,メモリの解放には十分注意することが必要である.

例題:

自然数のデ−タをキ−ボ−ドから入力し,それをリストとして順番に格納するプログラムを作成せよ.但し,デ−タはリストの末尾から先頭へ順番に格納し,0以下の整数値を入力すると, 入力操作は終了するものとする.

実行例:

自然数を入力して下さい.

2

3

4

5

9

12

0

出力

12

9

5

4

3

2

プログラム例:

#include <stdio.h>

#include <stdlib.h>

struct node_struct {

int data;

node *next;

};

typedef struct node_struct node;

main() {

node *start, *p;

int input;

start = NULL;

printf("自然数を入力してください¥n");

scanf("%d", &input);

while ( input >0 ) {

p = (node *) malloc(sizeof(node));

p -> next = NULL; /* malloc()で生成した構造体のメンバーには不定の値(予測できない値)が入っているので,まず初期化する */

p -> data = input;

p -> next = start;

start = p;

scanf("%d", &input);

}

printf("出力¥n");

for(p = start; p != NULL; p = p->next)

printf("%d¥n", p->data);

exit(0);

}

演習課題:

以下の問題について,前回の課題と合わせて,実行例とプログラムリストをレポ−トシステムにより提出せよ.尚,レポートシステム以外による提出は採点の対象外となる.

レポ−ト名:oomoto/program/struct   提出期限:12月25日(土)

問3.

上記の例は,リストの先頭からポインタが指す方向へ辿ると,入力した逆順に整数が格納される.これを反対に入力した順番に格納するプログラムを作成せよ.すなわち,自然数のデ−タをキ−ボ−ドから入力し,それをリストとして順番に格納してゆき,入力が終了したらリストの先頭から表示するプログラムを作成せよ.入力デ−タはリストの先頭から末尾へ順番に格納され,0以下の整数値を入力するとデータ入力操作は終了するものとする.


基礎プログラミング演習Iの表紙ページへ戻る