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;
}