CでVectorが使えないならそっれっぽいのを作ればいいというわけで、
昨晩チョコっとCで擬似的に作ったCVectorをメモメモ
戻り値とかコメントとかエラー処理が無かったり、 いろいろと中途半端だけど一応動きます。
Templateが使えないので、いちいちキャストが必要なことと、
複数vectorを管理したい時に、いちいちパラメータをセットしないといけないのが微妙です。。
たぶん良い解決方法があるんだと思うけど思いつかない!
main.c
#include "cvector.h" #include <stdio.h> int main() { /*■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ サンプルプログラム ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ */ /* ダミーデータ */ PHONE_LIST ts1; PHONE_LIST ts2; /* 実体 */ C_VECTOR ldata; memcpy(ts1.data.name, "bbbbb", sizeof("bbbbb")); memcpy(ts2.data.name, "aaaaa", sizeof("aaaaa")); /* C_VECTORのparameteセットと、開始 */ CVECTOR_PARAMETER_SET(&ldata); CVECTOR_START(&ldata, sizeof(PHONE_LIST)); int size; PHONE_LIST *tmp; /* push_back */ ldata.push_back(&ts1); size = ldata.size(); printf("%d\n", size); ldata.push_back(&ts2); size = ldata.size(); printf("%d\n", size); /* at */ tmp = (PHONE_LIST*)ldata.at(0); printf("%s\n", tmp->data.name); /* swap */ ldata.swap(0, 1); tmp = (PHONE_LIST*)ldata.at(0); printf("%s\n", tmp->data.name); /* erase */ ldata.erase(0); tmp = (PHONE_LIST*)ldata.at(0); printf("%s\n", tmp->data.name); /* insert */ ldata.insert(&ts1, 0); tmp = (PHONE_LIST*)ldata.at(0); printf("%s\n", tmp->data.name); /* clear */ ldata.clear(); size = ldata.size(); printf("%d\n", size); /* C_VECTORの開放 */ CVECTOR_END(); return 0; }
cvector.h
#ifndef __CVECTOR_H__ #define __CVECTOR_H__ /* 変数命令規則 */ #ifndef __VARIABLE_RULE__ #define __VARIABLE_RULE__ typedef unsigned int ui; typedef unsigned char u1; typedef unsigned short u2; typedef unsigned long int u4; typedef unsigned long long int u8; typedef signed int si; typedef signed char s1; typedef signed short s2; typedef signed long int s4; typedef signed long long int s8; #endif #ifndef __CPRINT__ #define __CPRINT__ #include <stdio.h> #define _PL(str) printf(str) #endif #ifndef __CFOR__ #define __CFOR__ #define FOR(i, j) for(i = 0; ((i) < (j)); ((i)++)) #endif /* リスト管理構造体 */ typedef struct VECLIST { struct VECLIST* next; /* 前要素 */ struct VECLIST* prev; /* 次要素 */ void* address; /* アドレス */ }VECLIST; typedef struct CVECTOR_PARAMETER { VECLIST* pri_head; /* 先頭要素 */ VECLIST* pri_tail; /* 最終要素 */ si pri_Elementcnt; /* 要素数 */ si pri_ElementSize; /* 要素サイズ */ si pri_EraseFlag; /* _Erase関数が呼ばれると1 */ VECLIST* Search_tmp; VECLIST* Search_tmp_next; si LastSearchNo; si search_firstflag; }CVECTOR_PARAMETER; typedef struct _C_VECTOR { /* 個々のリストを管理するためのparameter */ CVECTOR_PARAMETER parameter; void* (*at)(int _Dst); int (*insert)(void *_Src, int _Dst); int (*push_back)(void *_Src); int (*size)(); int (*swap)(int _target1, int _target2); int (*erase)(int _Dst); int (*clear)(); }C_VECTOR; /* プロトタイプ宣言 */ int CVECTOR_START(C_VECTOR *_Ldata, int Size); int CVECTOR_END(); void CVECTOR_PARAMETER_SET(C_VECTOR* _Src); #endif [/c] cvector.c [c] #include "cvector.h" #include <stdlib.h> #include <string.h> /* 静的プロトタイプ宣言 */ static VECLIST* Search(si _Dst); static void* _At(si _Dst); static si _Insert(void *_Src, si _Dst); static si _Push_back(void *_Src); static si _Size(); static si _Swap(si _target1, si _target2); static si _Erase(si _Dst); /* 静的グローバル変数 */ static CVECTOR_PARAMETER* g_parameter; /******************************************************************************* 概要 : 要素番号を検索します 説明 : 内部関数なので、外部から呼び出されることはありません Include : 引数 : 要素番号(int型) 戻り値 : VECLIST * Global : CVECTOR_PARAMETER g_parameter; *******************************************************************************/ static VECLIST* Search(si _Dst) { /* 最初の一回だけ処理 */ if(g_parameter->search_firstflag) { g_parameter->search_firstflag = 0; g_parameter->Search_tmp = g_parameter->pri_head; } /* 前回に_Erase関数が呼ばれていた */ if(g_parameter->pri_EraseFlag) { g_parameter->Search_tmp = g_parameter->Search_tmp_next; g_parameter->pri_EraseFlag = 0; } /* 前回検索した番号と今回検索する番号が同じだったなら */ if(g_parameter->LastSearchNo == _Dst) return g_parameter->Search_tmp; if((_Dst - g_parameter->LastSearchNo) > 0) { /* 前方向探査 */ si cnt; FOR(cnt, (_Dst - g_parameter->LastSearchNo)) { /* 末端まで検索したら強制終了 */ if(!g_parameter->Search_tmp->next) break; g_parameter->Search_tmp = g_parameter->Search_tmp->next; } } else { /* 後方向探査 */ si cnt; FOR(cnt, (g_parameter->LastSearchNo - _Dst)) { /* 末端まで検索したら強制終了 */ if(!g_parameter->Search_tmp->prev) break; g_parameter->Search_tmp = g_parameter->Search_tmp->prev; } } /* 最後に検索したリストの番号を記憶 */ g_parameter->LastSearchNo = _Dst; /* _Erase対策 */ g_parameter->Search_tmp_next =g_parameter-> Search_tmp->next; return g_parameter->Search_tmp; } /******************************************************************************* 概要 : 指定した要素を取り出します 説明 : void型のポインタが戻り値なので、明示的にキャストする必要があります。 Include : 引数 : 要素番号(int型) 戻り値 : void * Global : CVECTOR_PARAMETER g_parameter; *******************************************************************************/ static void* _At(si _Dst) { VECLIST* Search_tmp = Search(++_Dst); /* headかtailだった場合error */ if(!Search_tmp->address) return NULL; return (void*)Search_tmp->address; } /******************************************************************************* 概要 : リストへ要素を格納します 説明 : 登録したい要素を、指定した場所へ挿入します Include : 引数 : 要素のポインタ, 挿入したい場所(int型) 戻り値 : 成功なら0不成功なら1を返します Global : CVECTOR_PARAMETER g_parameter; *******************************************************************************/ static si _Insert(void *_Src, si _Dst) { void* data_tmp; VECLIST* list_tmp; VECLIST* Search_tmp = g_parameter->pri_head; data_tmp = malloc(g_parameter->pri_ElementSize); memmove(data_tmp, _Src, g_parameter->pri_ElementSize); list_tmp = (VECLIST*)calloc(1, sizeof(VECLIST)); list_tmp->address = data_tmp; Search_tmp = Search(_Dst); /* リストへ挿入 */ /*■ Search_tmp <-> list_tmp <-> Search_tmp->next ■*/ list_tmp->next = Search_tmp->next; list_tmp->prev = Search_tmp; Search_tmp->next->prev = list_tmp; Search_tmp->next = list_tmp; /* 要素数カウントアップ */ g_parameter->pri_Elementcnt++; return 0; } /******************************************************************************* 概要 : リストへ要素を格納します 説明 : 登録したい要素を一番最後のリストへ挿入 Include : 引数 : 要素のポインタ 戻り値 : 成功なら0不成功なら1を返します Global : CVECTOR_PARAMETER g_parameter; *******************************************************************************/ static si _Push_back(void *_Src) { /* 一番最後のリストへ挿入 */ _Insert(_Src, g_parameter->pri_Elementcnt); return 0; } /******************************************************************************* 概要 : 現在の要素の数を返します 説明 : 現在の要素の数をint型で返します。 Include : 引数 : 無し 戻り値 : 要素数(int型) Global : CVECTOR_PARAMETER g_parameter; *******************************************************************************/ static si _Size() { return g_parameter->pri_Elementcnt; } /******************************************************************************* 概要 : 指定された要素の場所を入れ替えます 説明 : 現在のparameterのセットされているリストを入れ替えますします Include : 引数 : 要素番号1(int型の数値), 要素番号2(int型の数値) 戻り値 : 成功なら0不成功なら1を返します Global : CVECTOR_PARAMETER g_parameter; *******************************************************************************/ static si _Swap(si _target1, si _target2) { VECLIST* Search_tmp1, * Search_tmp2; void* tmp; Search_tmp1 = Search(++_target1); Search_tmp2 = Search(++_target2); /* headかtailだった場合error */ if(!Search_tmp1->address || !Search_tmp2->address) return 1; /* 要素の入れ替え ※リストは変更しない */ tmp = Search_tmp1->address; Search_tmp1->address = Search_tmp2->address; Search_tmp2->address = tmp; return 0; } /******************************************************************************* 概要 : 指定された要素をクリアします 説明 : 現在のparameterのセットされているリストをクリアします Include : 引数 : 要素番号(int型の数値) 戻り値 : 成功なら0不成功なら1を返します Global : CVECTOR_PARAMETER g_parameter; *******************************************************************************/ static si _Erase(si _Dst) { VECLIST* Search_tmp; Search_tmp = Search(++_Dst); /* リストのつなぎ替え */ Search_tmp->prev->next = Search_tmp->next; Search_tmp->next->prev = Search_tmp->prev; /* リストと要素を開放 */ free(Search_tmp->address); free(Search_tmp); /* _Erase実行済みフラグON */ g_parameter->pri_EraseFlag = 1; g_parameter->pri_Elementcnt--; return 0; } /******************************************************************************* 概要 : リスト構造の要素をすべてクリアします 説明 : 現在のparameterのセットされているリストをクリアします Include : 戻り値 : 成功なら0不成功なら1を返します Global : CVECTOR_PARAMETER g_parameter; *******************************************************************************/ static si _Clear() { si cnt; si Frequency = g_parameter->pri_Elementcnt; FOR(cnt, Frequency) { _Erase(0); } return 0; } /* 外部関数 ----------------------------------------------*/ /******************************************************************************* 使い方 : 必ず最初に呼び出します。 概要 : CVECTORが利用するparameterをセットします 説明 : 複数のリストを管理するために、parameterを分離させます Include : cvector.h stdlib.h 引数 : C_VECTOR *_Ldata ;オブジェクト int Size ;リストの要素サイズを指定します 戻り値 : 成功なら0不成功なら1を返します Global : CVECTOR_PARAMETER g_parameter; *******************************************************************************/ void CVECTOR_PARAMETER_SET(C_VECTOR* _Src) { g_parameter = &_Src->parameter; } /******************************************************************************* 使い方 : 必ず最初に呼び出します。 概要 : CVECTORの全体の処理を開始します 説明 : 構造体の初期化と、メソッドをセットします Include : cvector.h stdlib.h 引数 : C_VECTOR *_Ldata ;オブジェクト int Size ;リストの要素サイズを指定します 戻り値 : 成功なら0不成功なら1を返します Global : CVECTOR_PARAMETER g_parameter; *******************************************************************************/ si CVECTOR_START(C_VECTOR *_Ldata, int Size) { /* リストの先頭と後尾の空要素作成 */ VECLIST* head = (VECLIST*)calloc(1, sizeof(VECLIST)); VECLIST* tail = (VECLIST*)calloc(1, sizeof(VECLIST)); /* parameterの初期化 */ memset(&_Ldata->parameter, 0, sizeof(_Ldata->parameter)); g_parameter->pri_head = head; g_parameter->pri_tail = tail; /* リスト構造の構築 */ g_parameter->pri_head->next = tail; g_parameter->pri_head->prev = NULL; g_parameter->pri_tail->prev = head; g_parameter->pri_tail->next = NULL; /* メソッドを構造体へ格納 */ _Ldata->at = _At; _Ldata->insert = _Insert; _Ldata->erase = _Erase; _Ldata->push_back = _Push_back; _Ldata->size = _Size; _Ldata->swap = _Swap; _Ldata->clear = _Clear; /* 要素サイズ格納 */ g_parameter->pri_ElementSize = Size; /* _Serch関数フラグ */ g_parameter->search_firstflag = 1; return 0; } /******************************************************************************* 使い方 : プラグラムの一番最後に必ず呼び出します 概要 : C_VECTORを終了します 説明 : 全ての要素をFreeしたあと、ダミーデータをFreeします Include : cvector.h stdlib.h 戻り値 : 成功なら0不成功なら1を返します Global : CVECTOR_PARAMETER g_parameter; *******************************************************************************/ si CVECTOR_END() { _Clear(); free(g_parameter->pri_head); free(g_parameter->pri_tail); return 0; }