# なぜ実装したのか?
一通りC言語の学習を終えて何か作ってみたくなったのでやってみた。
# 双方向リストとは
連結リストというデータ構造の仲間。
前後のリストの要素へのポインタを持っているのが特徴。
連結リストの仲間には片方向リストや循環リストがある。
詳しくはgoogle先生におまかせします。
# ソースコード
まずは全体
main.c
#include<stdio.h>
#include<stdlib.h>
typedef struct a_list {
int id; //ID
char *name; //名前
struct a_list *pre; //前のリストの要素へのポインタ
struct a_list *next; //次のリストの要素へのポインタ
} list;
//機能:Listが存在するかチェックする
//戻り値:Listが存在するなら0を、存在しないなら1を返す
int checkList(list *terget_List) {
if (terget_List == NULL) {
return 1;
} else {
return 0;
}
}
//機能:List構造体のメモリ領域を動的に確保する
//戻り値:確保に成功すればそのアドレスを、失敗すればプログラムを終了する
list *listLloc(void) {
list *pList;
pList = (list*)malloc(sizeof(list)); //メモリ領域を確保
if (pList == NULL) { //確保できているかチェック
exit(1);
}
return pList; //確保した領域のアドレスを返す
}
//機能:最後尾までリストを辿る
//戻り値:最後尾のリストの要素のアドレス
list *crawlList(list *crawler) {
while(crawler->next != NULL) { //nextの値がNULLのリストの要素までリストを降りていく
crawler = crawler->next;
}
return crawler;
}
//機能:リストが空なら新規に作成し、リストがあれば要素を追加する
//戻り値:リストの先頭のアドレス
list *addList(list *list_Head, int id, char *name) {
int check;
list* writer = NULL;
list* anchor = NULL;
check = checkList(list_Head); //リストが存在するかチェック
if (check == 1) { //リストを新規作成
writer = listLloc(); //追加するリストの領域を確保
writer->id = id; //構造体にデータを書き込む
writer->name = name;
writer->pre = NULL;
writer->next = NULL;
return writer; //リストの先頭のアドレスを返す
} else { //リストの要素の追加
anchor = crawlList(list_Head); //リストを最後尾まで辿り、最後尾のリストの要素のアドレスを受け取る
writer = listLloc(); //追加するリストも領域を確保
writer->id = id; //構造体にデータの書き込み
writer->name = name;
writer->pre = anchor;
writer->next = NULL;
anchor->next = writer; //追加したリストの要素と最後尾の要素を連結
return list_Head; //リストの先頭のアドレスを返す
}
}
//機能:リスト辿り全件削除する
void delList(list *closeList) {
while (closeList->next != NULL) { //リストを最後尾まで辿る
closeList = closeList->next; //リストを一つ降りる
free(closeList->pre); //一つ前のリストを削除
} //最後尾まできたらループを抜ける
free(closeList); //最後尾を削除
}
//機能:リストを辿り全件表示する
void putList(list *outList) {
while (outList != NULL) { リストを辿りながら要素を表示
printf("%d %s\n", outList->id, outList->name);
outList = outList->next;
}
}
int main(void) {
list *mainList = NULL; //リストの先頭要素へのポインタ
mainList = addList(mainList, 1001, "aiko"); //テストデータの入力
mainList = addList(mainList, 1002, "miko");
mainList = addList(mainList, 1003, "eri");
putList(mainList); //リストの要素を全件表示
delList(mainList); //リストの要素を全件削除
return 0;
}
## main
main以下の流れはこんな感じ。
①リストの先頭要素へのアドレスを格納するためのポインタ変数を宣言
②テストデータを関数に渡しリストを作成
③リストの要素を全件表示
④リストの要素を全件削除
main.c
int main(void) {
list *mainList = NULL; //リストの先頭要素へのポインタ ---①
mainList = addList(mainList, 1001, "aiko"); //テストデータの入力 ---②
mainList = addList(mainList, 1002, "miko");
mainList = addList(mainList, 1003, "eri");
putList(mainList); //リストの要素を全件表示 ---③
delList(mainList); //リストの要素を全件削除 ---④
return 0;
}
## 構造体
リストの要素を表現する構造体。IDと名前を格納する変数と前後のリストの要素へのアドレスを格納するポインタを持つ。
main.c
typedef struct a_list {
int id; //ID
char *name; //名前
struct a_list *pre; //前のリストの要素へのポインタ
struct a_list *next; //次のリストの要素へのポインタ
} list;
addList関数
本プログラムの本体と言っても過言ではない。リストの新規作成/要素の追加を担当している。
main.c
//機能:リストが空なら新規に作成し、リストがあれば要素を追加する
//戻り値:リストの先頭のアドレス
list *addList(list *list_Head, int id, char *name) {
int check;
list* writer = NULL;
list* anchor = NULL;
check = checkList(list_Head); //リストが存在するかチェック
if (check == 1) { //リストを新規作成
writer = listLloc(); //追加するリストの領域を確保
writer->id = id; //構造体にデータを書き込む
writer->name = name;
writer->pre = NULL;
writer->next = NULL;
return writer; //リストの先頭のアドレスを返す
} else { //リストの要素の追加
anchor = crawlList(list_Head); //リストを最後尾まで辿り、最後尾のリストの要素のアドレスを受け取る
writer = listLloc(); //追加するリストも領域を確保
writer->id = id; //構造体にデータの書き込み
writer->name = name;
writer->pre = anchor;
writer->next = NULL;
anchor->next = writer; //追加したリストの要素と最後尾の要素を連結
return list_Head; //リストの先頭のアドレスを返す
}
}
# 感想
全体的に説明が雑になってしまった。初投稿なので許して。
もう少し手を加えて実用性を高めてみたい。
蔵書管理プログラムにでもしようかな。
以上です。