A問題(50点)
演習問題1(リストの実装練習)
プログラム /home/course/prog1/public_html/2024/ex/ex09/prog00.c
、
ヘッダファイル /home/course/prog1/public_html/2024/ex/ex09/prog00.h
は、ハンドアウトLec09-19〜22 (pp.129-130) に出てきた、リストの基本操作を行うプログラムである。
これを各自prog00.c, prog00.h)として自分のディレクトリにコピーし、
ハンドアウトLec09-23 (p.130) 通りの動作を行う事を確認せよ。(これらのファイルは提出しない)
int
型の構造体メンバー key
を考えたが、
もう少し実用的なデータを扱うプログラムに変更する。id
)、姓 (surname
)、名 (givenname
)、及び年齢 (age
)を格納するRecord
型構造体を考えてみる。(提出ファイル名: prog01.c)
手順は以下の通り:prog00.h
と以下の手順を基に、studlist.h
の空欄を埋めて、ヘッダファイルを完成させなさい。id
)、姓 (surname
)、名 (givenname
)、及び年齢 (age
)を格納するRecord
型構造体を宣言する(すでに宣言済み)。Record
型の構造体変数 data
をデータとするリストを扱えるように、node構造体を宣言する。studlist.h
/* Record構造体の宣言 */ typedef struct { int id; char surname[12]; char givenname[12]; int age; } Record; /* node構造体の宣言 */ typedef ________ ________ *NodePointer; struct node { ________ data; ________ next; }; /* プロトタイプ宣言 */ NodePointer insert(Record); /* 新しいノード挿入関数 */ NodePointer finditem(int); /* リスト内の重複するノード検索関数 */ void listprint(void); /* リスト内データの表示関数 */ NodePointer make_1node(Record, NodePointer); /* 新しいノード作成関数 */ /* グローバル変数 head */ NodePointer head;
prog00.c
と以下の手順を基に、prog01.c
の空欄を埋めて、プログラムを完成させなさい。studlist.h
)をインクルードする。main
関数
listprint
関数で現在のリストを出力する。なお、headノードを作る際、ノードの内容は意味のある情報でなくてよく、宣言されているRecord
型の変数をmake_1node
関数の1つ目の引数として渡すこと。insert
関数を用いて順次新しいノードをリストに挿入する。その後、毎回 listprint
関数でリスト全体を出力する。insert
関数が NULL を返した場合は、ID番号に対するメッセージを表示する。insert
関数
Record
型の引数をとる。finditem
関数を用いて構造体変数 data
内のメンバーid
が重複するノードがリスト中にあるか調べる。make_1node
関数を用いて新しいノードを作成し、headノードの下に新しいノードをつなぐ。listprint
関数
data
内のデータを(ID番号、姓、名、年齢)の順で順次出力する。finditem
関数
data
のメンバー id
の値と同じ値があるか、headからNULLの一つ前までのノードを検索する。make_1node
関数
Record
型をとり、2つ目の引数はNodePointer
型をとる。malloc
関数を用いて、ノード1個分のメモリを割り当てる。node
構造体のメンバーであるdata
とnext
に引数の値をセットする。prog01.c
#include <stdio.h> #include <stdlib.h> #include ________ int main() { Record r; int i; /* リストの初期化 */ head = make_1node( ________, NULL ); listprint(); /* 新しいノードをリストに追加する */ /* CTL+D でループを抜ける */ while (1) { printf("Insert new student data: (ID Surname Givenname Age) -> "); if (scanf("%d %s %s %d", ________, ________, ________, ________) != 4) { printf("\n"); break; } if (insert(________) == NULL) { printf("ID %d is already on the list!\n", ________); } listprint(); } printf("\n"); return 0; } NodePointer insert(Record r) { NodePointer newnode; if (finditem(________) == NULL) { /* 重複するノードの検索 */ newnode = make_1node(________, ________); /* headの下に新しいノードを作成 */ ________ = newnode; /* headの下に新しいノードをつなぐ */ return newnode; } else return NULL; } void listprint(void) { NodePointer n; printf("Head - \n"); for(n = ________; ________; n = ________){ /* headの次のノードからNULLの前までたどる */ printf(" %7d %-12s %-12s %d\n", ________, ________, ________, ________); } printf("\n"); } NodePointer finditem(int sid) { NodePointer n; for (n = ________; ________; n = ________) { /* headからNULLの一つ前までのノードをたどる */ if (________ == sid) return ________; /* sidと同じ値が見つかったら一つ手前のノードを指すポインタを返す */ } return NULL; } NodePointer make_1node(Record r, NodePointer p) { NodePointer n; if ((n = (________)malloc(________) ) == NULL) { /* メモリ確保 */ printf("Error in memory allocation\n"); exit(8); } /* dataとnextに引数の値をセットする */ ________ = ________; ________ = ________; return n; }
% ./a.out Head - Insert new student data: (ID Surname Givenname Age) -> 1301001 AIZU Taro 19 Head - 1301001 AIZU Taro 19 Insert new student data: (ID Surname Givenname Age) -> 1301022 BANDAI Hanako 22 Head - 1301022 BANDAI Hanako 22 1301001 AIZU Taro 19 Insert new student data: (ID Surname Givenname Age) -> 1301033 TSURUGA Shirou 21 Head - 1301033 TSURUGA Shirou 21 1301022 BANDAI Hanako 22 1301001 AIZU Taro 19 Insert new student data: (ID Surname Givenname Age) -> 1301001 AIZU Jiro 18 ID 1301001 is already on the list! Head - 1301033 TSURUGA Shirou 21 1301022 BANDAI Hanako 22 1301001 AIZU Taro 19 Insert new student data: (ID Surname Givenname Age) -> Ctrl-D %
%12s
のように%s
に対する桁数指定を行うと、指定分の桁数の表示幅が確保されて、その桁数内での右詰めの表示になる。また、%-12s
のように桁数指定値に負号を付けると左詰めとなる(表示例ではこの方法を用いている)。printf
関数の桁数に関する書式指定についてはハンドアウトp.16のLec03-14で説明されている%d
についての内容が%s
に対しても適用できる。
B問題
演習問題2(リストの拡張)
prog01.c
を prog02.c
にコピーし、 prog02.c
に以下のような機能を追加したプログラムにせよ。最初に、/home/course/prog1/public_html/2024/ex/ex09/Student.txt
を自分のディレクトリにコピーしなさい。
listprint()
で一度リスト全体を表示する。
prog01.c
と同じくキーボードからのデータとリストへの追加が行えるようにすること。ID番号が重複していた場合の動作も元のまま残すこと。
insert()
を修正して、新しいノードをリストの先頭(head
の次)ではなくリストの最後に挿入するようにする。具体的には以下の通りである。
insert()
では、入力されたID番号が既にリスト中にあるか finditem
関数を使ってチェックし、
有った場合は前と同様に挿入を行わず NULL を返す。無ければ、ノードを最後までたどってリストの最後に挿入し、
挿入したノードへのポインタを返す。listprint()
を修正して、ノード内容の一覧表示の後にノードの数(Headは含まない)を表示するようにする。
finditem
関数には手を加えない。また外部変数も追加しないこととする。
prog01.c
を prog02.c
に、コピーしてから、prog02.c
を修正すると良い。問題1で使用したstudlist.h
をそのまま用いて、変更する必要はない。
% ./a.out Head - 1301001 AIZU Taro 19 1301022 BANDAI Hanako 22 1301033 TSURUGA Shirou 21 .....(中略) 1301150 KITAKATA Testuo 18 1301164 SUKAGAWA Yoshiko 18 1301200 ASHINOMAKI Masaru 19 14 nodes exist in the list. Insert new student data: (ID Surname Givenname Age) -> 1301001 AIZU Jiro 18 ID 1301001 is already on the list! Head - 1301001 AIZU Taro 19 1301022 BANDAI Hanako 22 1301033 TSURUGA Shirou 21 .....(中略) 1301150 KITAKATA Testuo 18 1301164 SUKAGAWA Yoshiko 18 1301200 ASHINOMAKI Masaru 19 14 nodes exist in the list. Insert new student data: (ID Surname Givenname Age) -> 1301100 IKKI Goro 18 Head - 1301001 AIZU Taro 19 1301022 BANDAI Hanako 22 1301033 TSURUGA Shirou 21 .....(中略) 1301150 KITAKATA Testuo 18 1301164 SUKAGAWA Yoshiko 18 1301200 ASHINOMAKI Masaru 19 1301100 IKKI Goro 18 15 nodes exist in the list. Insert new student data: (ID Surname Givenname Age) -> Ctrl-D %
演習問題3(削除の実装)
演習問題2のプログラムにノードを削除する機能を追加する。
prog02.c
を prog03.c
に、studlist.h
を studlist03.h
にコピーしてから、prog03.c
とstudlist03.h
を適宜修正して作成すること。今度はヘッダファイルも修正する必要があるので注意すること。
delete
関数を追加する。
delete
関数のプロトタイプは
NodePointer delete(int);とし、以下のような動作を行う。
data
のメンバー id
が同じ値をもつノードを検索する
NULL
をリターンする。 studlist03.h
に delete
関数のプロトタイプ宣言を追加する。main
関数を修正する。insert
関数を用いる
delete
関数を用いる。なお、削除すべきノードが存在しない場合はその旨のメッセージを表示すること
% ./a.out Head - 1301001 AIZU Taro 19 1301022 BANDAI Hanako 22 1301033 TSURUGA Shirou 21 .....(中略) 1301150 KITAKATA Testuo 18 1301164 SUKAGAWA Yoshiko 18 1301200 ASHINOMAKI Masaru 19 14 nodes exist in the list. Choose operation (1: Insert, 0: Delete, ^D: Finish) -> 1 Insert new student data: (ID Surname Givenname Age) -> 1301100 IKKI Goro 18 Head - 1301001 AIZU Taro 19 1301022 BANDAI Hanako 22 1301033 TSURUGA Shirou 21 .....(中略) 1301150 KITAKATA Testuo 18 1301164 SUKAGAWA Yoshiko 18 1301200 ASHINOMAKI Masaru 19 1301100 IKKI Goro 18 15 nodes exist in the list. Choose operation (1: Insert, 0: Delete, ^D: Finish) -> 0 Delete ID -> 1209001 ID 1209001 is not found. Head - 1301001 AIZU Taro 19 1301022 BANDAI Hanako 22 1301033 TSURUGA Shirou 21 .....(中略) 1301150 KITAKATA Testuo 18 1301164 SUKAGAWA Yoshiko 18 1301200 ASHINOMAKI Masaru 19 1301100 IKKI Goro 18 15 nodes exist in the list. Choose operation (1: Insert, 0: Delete, ^D: Finish) -> 0 Delete ID -> 1301022 Head - 1301001 AIZU Taro 19 1301033 TSURUGA Shirou 21 .....(中略) 1301150 KITAKATA Testuo 18 1301164 SUKAGAWA Yoshiko 18 1301200 ASHINOMAKI Masaru 19 1301100 IKKI Goro 18 14 nodes exist in the list. Choose operation (1: Insert, 0: Delete, ^D: Finish) -> Ctrl-D %
Extra問題
演習問題4(降順/昇順の挿入)
演習問題2のプログラムを改良して、ノードをIDの降順、または昇順に挿入する機能を追加する。
prog02.c
を prog04.c
に、studlist03.h
を studlist04.h
にコピーしてから、prog04.c
とstudlist04.h
を適宜修正して作成すること。
NodePointer insert_sort(Record, char);
を作成して利用せよ。
ここで、insert_sort
関数の
第一引数は入力ノードを示す引数、
第二引数は降順か昇順かを指定する引数である。% ./a.out Enter sort mode (d:descending / a:ascending) -> d Head - 1301200 ASHINOMAKI Masaru 19 1301164 SUKAGAWA Yoshiko 18 1301150 KITAKATA Testuo 18 1301123 SOUMA Hikaru 19 1301099 IWAKI Youko 18 .....(中略) 1301007 FUKUSHIMA Ichiro 20 1301004 BANGE Jiro 18 1301001 AIZU Taro 19 14 nodes exist in the list. Insert new student data: (ID Surname Givenname Age) -> 1301100 IKKI Goro 18 Head - 1301200 ASHINOMAKI Masaru 19 1301164 SUKAGAWA Yoshiko 18 1301150 KITAKATA Testuo 18 1301123 SOUMA Hikaru 19 1301100 IKKI Goro 18 1301099 IWAKI Youko 18 .....(中略) 1301001 AIZU Taro 19 15 nodes exist in the list. Insert new student data: (ID Surname Givenname Age) -> Ctrl-D % % ./a.out Enter sort mode (d:descending / a:ascending) -> a Head - 1301001 AIZU Taro 19 1301004 BANGE Jiro 18 1301007 FUKUSHIMA Ichiro 20 .....(中略) 1301150 KITAKATA Testuo 18 1301164 SUKAGAWA Yoshiko 18 1301200 ASHINOMAKI Masaru 19 14 nodes exist in the list. Insert new student data: (ID Surname Givenname Age) -> 1301003 INAWASHIRO Fumiko 18 Head - 1301001 AIZU Taro 19 1301003 INAWASHIRO Fumiko 18 1301004 BANGE Jiro 18 1301007 FUKUSHIMA Ichiro 20 .....(中略) 1301150 KITAKATA Testuo 18 1301164 SUKAGAWA Yoshiko 18 1301200 ASHINOMAKI Masaru 19 15 nodes exist in the list. Insert new student data: (ID Surname Givenname Age) -> Ctrl-D %