listライブラリ
Cでstlのリストっぽいことをやってみた。
Nextと対照的にprevを実装すべきだが、とりあえずってことで。
今のところ格納しているのはintに決め打ちだがvoid *で持てば、汎用的に保持できる。
しかし、デストラクタがめんどい。
list.h
#ifndef LIST_H__ #define LIST_H__ /* Listコンテナライブラリ */ /* List構造体宣言 */ /* 実装詳細を隠蔽するため名前のみ公開 */ /* とりあえず格納するのはint */ typedef struct List List; /* Listコンストラクタ */ List *ListCreate(void); /* Listデストラクタ */ void ListDispose(List *pList); /* Listダンプ */ void ListDump(List *pList); /* ListIterator構造体宣言 */ /* 実装詳細を隠蔽するため名前のみ公開 */ typedef struct ListIterator ListIterator; /* ListIteratorコンストラクタ */ ListIterator *ListIteratorCreate(List *pList); /* ListIteratorデストラクタ */ void ListIteratorDispose(ListIterator *pIte); /* Next可能か? */ /* Next可能なら1, 不可なら0を返す */ int ListIteratorHasNext(ListIterator *pIte); /* Nextしてオブジェクト(int)を返す */ int ListIteratorNext(ListIterator *pIte); /* pIteの次にdataを格納したノードを追加する。 */ void ListIteratorInsertNext(ListIterator *pIte, int data); /* pIteが指しているノードを切り離し、格納していた値を返す。 */ /* ノードは開放される。pIteがは元のノードのprevを指すようになる。 */ int ListIteratorErase(ListIterator *pIte); #endif /* LIST_H__ */
list.c
#include <stdio.h> #include <stdlib.h> #include "list.h" /* Listコンテナライブラリ */ /* Node構造体 */ /* 非公開構造体 */ typedef struct M_Node { struct M_Node *pPrev; struct M_Node *pNext; int data; } M_Node; /* List構造体宣言 */ /* とりあえず格納するのはint */ struct List { M_Node dummyNode; /* リストの先頭、最後尾を指すダミーノード */ }; /* Listコンストラクタ */ List *ListCreate(void) { List *p = malloc(sizeof(List)); if (p) { /* ダミーノードなので牛の死体を置いておく*/ p->dummyNode.data = 0xdeadbeef; /* ダミーノードを始点終点として循環させる。 */ p->dummyNode.pPrev = &p->dummyNode; p->dummyNode.pNext = &p->dummyNode; } return p; } /* Listデストラクタ */ void ListDispose(List *pList) { M_Node *pTmp, *pDelete; /* 引数チェック */ if (pList == NULL) { return; } /* リストの各ノードを開放 */ pTmp = pList->dummyNode.pNext; while (pTmp != &pList->dummyNode) { /* 切り離すノードを保持 */ pDelete = pTmp; /* ノードをすすめる */ pTmp = pTmp->pNext; /* ノードを切り離す */ pDelete->pNext = pDelete->pPrev = NULL; /* ノード開放 */ free(pDelete); } /* リストを開放 */ free(pList); } /* Listダンプ */ void ListDump(List *pList) { int i = 0; /* イテレータ生成 */ ListIterator *pIte = ListIteratorCreate(pList); printf("==== Dump List ====\n"); if (pIte) { while (ListIteratorHasNext(pIte)) { printf("%d: %d\n", ++i, ListIteratorNext(pIte)); } } /* イテレータ開放 */ ListIteratorDispose(pIte); } /* ListIterator構造体宣言 */ /* 実装詳細を隠蔽するため名前のみ公開 */ struct ListIterator { List *pList; /* リストを保持 */ M_Node *pNode; /* 現時点のノードを保持 */ }; /* ListIteratorコンストラクタ */ ListIterator *ListIteratorCreate(List *pList) { ListIterator *pIte = malloc(sizeof(ListIterator)); /* 引数チェック */ if (pList == NULL) { return NULL; } if (pIte) { pIte->pList = pList; pIte->pNode = &pList->dummyNode; } return pIte; } /* ListIteratorデストラクタ */ void ListIteratorDispose(ListIterator *pIte) { free(pIte); } /* Next可能か? */ /* Next可能なら1, 不可なら0を返す */ int ListIteratorHasNext(ListIterator *pIte) { if (pIte == NULL) { return 0; } if (pIte->pNode->pNext != &pIte->pList->dummyNode) { return 1; } else { return 0; } } /* Nextしてオブジェクト(int)を返す */ int ListIteratorNext(ListIterator *pIte) { pIte->pNode = pIte->pNode->pNext; return pIte->pNode->data; } /* pIteの次にdataを格納したノードを追加する。 */ void ListIteratorInsertNext(ListIterator *pIte, int data) { M_Node *pNewNode = malloc(sizeof(M_Node)); if (pNewNode) { pNewNode->data = data; /* ノードをつなぐ */ pNewNode->pPrev = pIte->pNode; pNewNode->pNext = pIte->pNode->pNext; pIte->pNode->pNext = pNewNode; pNewNode->pNext->pPrev = pNewNode; } } /* pIteが指しているノードを切り離し、格納していた値を返す。 */ /* ノードは開放される。pIteがは元のノードのprevを指すようになる。 */ /* 切り離しに失敗したら0が返る */ int ListIteratorErase(ListIterator *pIte) { M_Node *pPrev, *pNext; int rtn; if (pIte == NULL) { return 0; } if (pIte->pNode == &pIte->pList->dummyNode) { /* ダミーノードは切り離せない */ return 0; } pPrev = pIte->pNode->pPrev; pNext = pIte->pNode->pNext; /* 前と後ろをつなげる */ pPrev->pNext = pNext; pNext->pPrev = pPrev; rtn = pIte->pNode->data; /* Node開放 */ free(pIte->pNode); /* イテレータはひとつ前を指す */ pIte->pNode = pPrev; return rtn; }
main.c
#include <stdio.h> #include "list.h" int main(void) { List *pList; ListIterator *pIte; pList = ListCreate(); pIte = ListIteratorCreate(pList); /* リストに挿入 */ ListIteratorInsertNext(pIte, 0); ListIteratorInsertNext(pIte, 1); ListIteratorInsertNext(pIte, 2); ListIteratorInsertNext(pIte, 3); ListIteratorInsertNext(pIte, 4); ListIteratorInsertNext(pIte, 5); /* リストダンプ */ ListDump(pList); /* 2つすすめる */ ListIteratorNext(pIte); ListIteratorNext(pIte); /* リストに挿入 */ ListIteratorInsertNext(pIte, 10); ListIteratorInsertNext(pIte, 11); ListIteratorInsertNext(pIte, 12); /* リストダンプ */ ListDump(pList); /* 5つすすめる */ ListIteratorNext(pIte); ListIteratorNext(pIte); ListIteratorNext(pIte); ListIteratorNext(pIte); ListIteratorNext(pIte); /* 3つリストから削除 */ ListIteratorErase(pIte); ListIteratorErase(pIte); ListIteratorErase(pIte); /* リストダンプ */ ListDump(pList); /* イテレータ開放 */ ListIteratorDispose(pIte); /* リスト開放 */ ListDispose(pList); return 0; }