A問題(50点)
演習問題1(リストの実装練習)
プログラム /home/course/prog1/public_html/2026/ex/ex09/prog00.c、
ヘッダファイル /home/course/prog1/public_html/2026/ex/ex09/prog00.h
は、ハンドアウトLec09-19〜22 (pp.130-131) に出てきた、リストの基本操作を行うプログラムである。
これを各自prog00.c, prog00.hとして自分のディレクトリにコピーし、
ハンドアウトLec09-23 (p.131) 通りの動作を行う事を確認せよ。(これらのファイルは提出しない)
int型の構造体メンバー key を考えたが、
もう少し実用的なデータを扱うプログラムに変更する。id)、姓 (surname)、名 (givenname)、及びGPA (gpa)を格納するRecord型構造体を考えてみる。学生のID番号は正であるとする。(提出ファイル名: prog01.c, studlist.h)
手順は以下の通り:prog00.h と以下の手順を基に、studlist.hの空欄を埋めて、ヘッダファイルを完成させなさい。id)、姓 (surname)、名 (givenname)、及びGPA (gpa)を格納するRecord型構造体を宣言する(すでに宣言済み)。Record型の構造体変数 data をデータとするリストを扱えるように、node構造体を宣言する。studlist.h
/* Record構造体の宣言 */
typedef struct {
int id;
char surname[12];
char givenname[12];
double gpa;
} 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型の変数rをmake_1node 関数の1つ目の引数として渡している。insert 関数を用いて順次新しいノードをリストに挿入する。その後、毎回 listprint 関数でリスト全体を出力する。insert 関数が NULL を返した場合は、ID番号に対するメッセージを表示する。insert 関数
Record型の引数をとる。finditem 関数を用いて構造体変数 data 内のメンバーidが重複するノードがリスト中にあるか調べる。make_1node関数を用いて新しいノードを作成し、headノードの下に新しいノードをつなぐ。listprint 関数
data 内のデータを(ID番号、姓、名、GPA)の順で順次出力する。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;
/* リストの初期化 */
/* headノードの内容は意味のある情報でなくてよい */
r.id = 0;
head = make_1node( r,________);
listprint();
/* 新しいノードをリストに追加する */
/* CTL+D でループを抜ける */
while (1) {
printf("Insert new student data: (ID Surname Givenname GPA) -> ");
if (scanf("%d %s %s %lf", ________, ________, ________, ________) != 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 %5.2f\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に引数の値をセットする */
n->data = ________;
n->next = ________;
return n;
}
% ./a.out
Head -
Insert new student data: (ID Surname Givenname GPA) -> 1301001 AIZU Taro 3.5
Head -
1301001 AIZU Taro 3.50
Insert new student data: (ID Surname Givenname GPA) -> 1301022 BANDAI Hanako 3.15
Head -
1301022 BANDAI Hanako 3.15
1301001 AIZU Taro 3.50
Insert new student data: (ID Surname Givenname GPA) -> 1301033 TSURUGA Shirou 2.9
Head -
1301033 TSURUGA Shirou 2.90
1301022 BANDAI Hanako 3.15
1301001 AIZU Taro 3.50
Insert new student data: (ID Surname Givenname GPA) -> 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/2026/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 3.50
1301022 BANDAI Hanako 3.15
1301033 TSURUGA Shirou 2.90
.....(中略)
1301150 KITAKATA Testuo 3.55
1301164 SUKAGAWA Yoshiko 3.20
1301200 ASHINOMAKI Masaru 3.00
14 nodes exist in the list.
Insert new student data: (ID Surname Givenname GPA) -> 1301001 AIZU Taro 3.5
ID 1301001 is already on the list!
Head -
1301001 AIZU Taro 3.50
1301022 BANDAI Hanako 3.15
1301033 TSURUGA Shirou 2.90
.....(中略)
1301150 KITAKATA Testuo 3.55
1301164 SUKAGAWA Yoshiko 3.20
1301200 ASHINOMAKI Masaru 3.00
14 nodes exist in the list.
Insert new student data: (ID Surname Givenname GPA) -> 1301100 IKKI Goro 3.0
Head -
1301001 AIZU Taro 3.50
1301022 BANDAI Hanako 3.15
1301033 TSURUGA Shirou 2.90
.....(中略)
1301150 KITAKATA Testuo 3.55
1301164 SUKAGAWA Yoshiko 3.20
1301200 ASHINOMAKI Masaru 3.00
1301100 IKKI Goro 3.00
15 nodes exist in the list.
Insert new student data: (ID Surname Givenname GPA) -> 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 3.50
1301022 BANDAI Hanako 3.15
1301033 TSURUGA Shirou 2.90
.....(中略)
1301150 KITAKATA Testuo 3.55
1301164 SUKAGAWA Yoshiko 3.20
1301200 ASHINOMAKI Masaru 3.00
14 nodes exist in the list.
Choose operation (1: Insert, 0: Delete, ^D: Finish) -> 1
Insert new student data: (ID Surname Givenname GPA) -> 1301100 IKKI Goro 3.00
Head -
1301001 AIZU Taro 3.60
1301022 BANDAI Hanako 3.15
1301033 TSURUGA Shirou 2.90
.....(中略)
1301150 KITAKATA Testuo 3.55
1301164 SUKAGAWA Yoshiko 3.20
1301200 ASHINOMAKI Masaru 3.00
1301100 IKKI Goro 3.00
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 3.50
1301022 BANDAI Hanako 3.15
1301033 TSURUGA Shirou 2.90
.....(中略)
1301150 KITAKATA Testuo 3.55
1301164 SUKAGAWA Yoshiko 3.20
1301200 ASHINOMAKI Masaru 3.00
1301100 IKKI Goro 3.00
15 nodes exist in the list.
Choose operation (1: Insert, 0: Delete, ^D: Finish) -> 0
Delete ID -> 1301022
Head -
1301001 AIZU Taro 3.50
1301033 TSURUGA Shirou 2.90
.....(中略)
1301150 KITAKATA Testuo 3.55
1301164 SUKAGAWA Yoshiko 3.20
1301200 ASHINOMAKI Masaru 3.00
1301100 IKKI Goro 3.00
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 3.00
1301164 SUKAGAWA Yoshiko 3.20
1301150 KITAKATA Testuo 3.55
1301123 SOUMA Hikaru 3.80
1301099 IWAKI Youko 3.90
.....(中略)
1301007 FUKUSHIMA Ichiro 3.60
1301004 BANGE Jiro 3.40
1301001 AIZU Taro 3.50
14 nodes exist in the list.
Insert new student data: (ID Surname Givenname GPA) -> 1301100 IKKI Goro 3.0
Head -
1301200 ASHINOMAKI Masaru 3.00
1301164 SUKAGAWA Yoshiko 3.20
1301150 KITAKATA Testuo 3.55
1301123 SOUMA Hikaru 3.80
1301100 IKKI Goro 3.00
1301099 IWAKI Youko 3.90
.....(中略)
1301001 AIZU Taro 3.50
15 nodes exist in the list.
Insert new student data: (ID Surname Givenname GPA) -> Ctrl-D
%
% ./a.out
Enter sort mode (d:descending / a:ascending) -> a
Head -
1301001 AIZU Taro 3.50
1301004 BANGE Jiro 3.40
1301007 FUKUSHIMA Ichiro 3.60
.....(中略)
1301150 KITAKATA Testuo 3.55
1301164 SUKAGAWA Yoshiko 3.20
1301200 ASHINOMAKI Masaru 3.00
14 nodes exist in the list.
Insert new student data: (ID Surname Givenname GPA) -> 1301003 INAWASHIRO Fumiko 3.7
Head -
1301001 AIZU Taro 3.50
1301003 INAWASHIRO Fumiko 3.70
1301004 BANGE Jiro 3.40
1301007 FUKUSHIMA Ichiro 3.60
.....(中略)
1301150 KITAKATA Testuo 3.55
1301164 SUKAGAWA Yoshiko 3.20
1301200 ASHINOMAKI Masaru 3.00
15 nodes exist in the list.
Insert new student data: (ID Surname Givenname GPA) -> Ctrl-D
%