第11回 線型リスト・その3(6/19)
今日のキーワード
■ 分割コンパイル
ファイルの準備
前回まで作成してきたリストのプログラムより、定数(define)、構造体宣言、および、関数名宣言の各部分を1つのファイルにまとめ、関数本体の部分をもう1つのファイルにまとめる。そして、メイン関数およびそのサブルーチンを、別のファイルにまとめる。
コンパイル方法
- 手作業の場合
$ gcc -c numlist.c
$ gcc -c list1101.c
$ gcc -o list1101 numlist.o list1101.o
numlist.c と list1101.c は別々にコンパイルする。最後に両者をリンクする。
実行は、./a.out ではなく ./list1101 とする。
- 自動の場合
3つのコマンドを入力することは面倒である。Unixでは通常 make コマンドを使う。そのために、Makefile という設定ファイルを作る。
- Makefile を作る。
- コマンドラインから以下を実行する。
$ make list1101
実行は、./a.out ではなく ./list1101 とする。
make clean を実行すると、不要なファイルが自動的に削除される。
Makefile では、連続する2つ以上のスペースは使わず、TABを使う。
新しいプログラムの追加方法
新しいプログラム list1102.c を追加するには、Makefile に次を追加する。
list1102: list1102.o numlist.o
$(LD) list1102.o numlist.o -o list1102
list1102.o: numlist.h list1102.c
$(CC) -c list1102.c
また、clean:; についても以下のように変更する。
clean:; @rm -f *.o core list1101 list1102
後始末
プログラム作成の練習を終えると、make clean コマンドにより、オブジェクトファイル、実行ファイル、および、コアファイル(セグメンテーションフォールト時などに作られる)を削除する。ユーザの使用可能なディスク容量は限られているため、不要なファイルはこまめに削除すること。
□ 演習1
リスト中の偶数である値の総和を求める関数 int list_even_sum(Node *); を list1101.c にならって作成せよ。そして、Makefile に list1102 を追加して、コンパイルおよび動作を確認せよ。デバッグの際、list1102.c を更新すると、list1102.c はコンパイルされるが、lnumlist.c は2回目以降は、コンパイルされないことに注意せよ。
■ 削除
□ 例題
- リストの先頭要素を削除する関数は、pop の関数として既に作成した。今回は、指定値と一致するノードを削除する関数 void list_delete(Node *, int); を作成する。なお、削除対象のノードが存在しない場合は、リスト変更をせず、エラー出力もせずに削除関数を終了することとする。
- 手始めに、演習1と同様に、既存のプログラム(list1102.c)の一部を書き換えて、list_delete 関数を作成せよ。⇒ list1103.c もちろん、 Makefile も更新すること。
- list_delete は次のようになる。
void list_delete(Node *root, int num){
Node *p;
p は root と同じノードを指す;
while ( p の指しているノードの次がNULLでない ) {
if ( p の指しているノードの次のノードの値が num である ) {
q は p の指しているノードの次のノードを指す
p の指しているノードの次ノードを、q の指しているノードの次ノードとする
q の指しているノードを free する
break;
}
p = p -> next; /* p は p の指しているノードの次ノードとする */
}
}
□ 演習2
- もし、リストが昇順に並んでいることがわかっている(すなわち、insert 操作だけでリストが作られた)場合ならば、delete 操作は途中で中止することができる。つまり、指定値よりも注目しているノードの値が大きい場合は、これ以上ノードを辿っても無駄だからである。そこで、昇順を想定して削除を行う関数 void list_delete_s(Node *, int); を作れ。⇒ prac1101.c なお、削除対象が存在しない場合は、例題と同様に終了する。また、list1103.c と同様、numlist.c は変更せずに、prac1101.c を作成せよ。もちろん、Makefile は更新する。
■ 宿題
- 数のリストで最初に数字のあるノードを 0 番目とするとき、n 番目のノードを削除する関数 void list_delete_n(Node *, int); を作成せよ。また、該当番目の無い場合は、例題と同様に終了せよ。また、この削除関数は、ファイル prac1102.c に作成せよ。prac1102.c には動作確認のための main 関数を含むこと。
- prac1102.c、Makefile、および、動作結果を報告せよ。numlist.c は変更不要のはずなので、提出しないこと。
(c) Masato TOKUHISA, 2003, June.18