他言語でいうString型の様な、メモリサイズ(配列長)を気にせずに使える可変長文字列型をC言語で自作するサンプルです。
まぁ、普通でしたらC++使えば良いのですが。そこをC言語でやってみようという、あまり需要は無いかも知れないですね。
C言語ライブラリ「cmn-clib」に同じものがありますので、作るのがめんどくさい人はこちらからコピーでも。「CmnStringBuffer_xxx」という名前の関数がそれです。
使い方イメージ
可変長文字列型の名前は「CmnStringBuffer」としています。
Createでバッファを作成し、Setで文字列の設定、Appendで追加をします。使い終わったらFreeでメモリ開放です。
/* 可変長文字列の生成 */
CmnStringBuffer *buf = CmnStringBuffer_Create("hello");
printf(buf->string); /* hello */
/* データをセット(上書き) */
CmnStringBuffer_Set(buf, "HELLO!");
printf(buf->string); /* HELLO! */
/* データを追加 */
CmnStringBuffer_Append(buf, "123");
printf(buf->string); /* HELLO!123 */
printf("文字列長:%d", buf->length); /* 文字列長:9 */
/* 可変長文字列の破棄 */
CmnStringBuffer_Free(buf);
CmnStringBufferの実装
このプログラムは以下のページで作成したCmnDataBufferを拡張したものですので、こちらも合わせてご覧ください。
データ構造
可変長文字列型を構造体として定義します。
typedef struct _tag_CmnStringBuffer {
CmnDataBuffer *_buf; /**< 自動領域拡張バッファへのポインタ。内部的な処理で使う。 */
char *string; /**< 文字列へのポインタ。Append/Setによる領域拡張時にアドレスが変わる可能性があるため、利用側で保存せず、常に最新のポインタを参照すること。 */
size_t length; /**< 文字数 */
} CmnStringBuffer;
関数
CmnStringBuffer_Create : 文字列バッファ作成
引数strの文字列を初期値として、バッファを新規作成します。
/**
* @brief 文字列バッファ作成
*
* 自動領域拡張をする文字列バッファを新規に作成する。
*
* @param str 文字列バッファに格納する文字列。NULLを指定した場合は空文字列を設定する。
* @return 作成したバッファへのポインタ。作成に失敗した場合はNULLを返す。
*/
CmnStringBuffer* CmnStringBuffer_Create(const char *str)
{
size_t strLen = 0;
CmnStringBuffer *ret;
ret = malloc(sizeof(CmnStringBuffer));
if (ret == NULL) {
return NULL;
}
if (str == NULL) {
str = "";
}
strLen = strlen(str);
ret->_buf = CmnDataBuffer_Create(strLen + 1);
if (ret->_buf == NULL) {
return NULL;
}
CmnDataBuffer_Set(ret->_buf, str, strLen + 1);
ret->string = ret->_buf->data;
ret->length = strLen;
return ret;
}
CmnStringBuffer_Set : 文字列設定(上書き)
文字列を上書き設定します。元々設定されていた文字列は破棄され、引数strの内容で上書きされます。内部的には CmnDataBuffer を使っており、バッファ領域の拡張は CmnDataBuffer が行っています。
/**
* @brief 文字列バッファへのデータ設定 *
* 文字列バッファにデータを設定する。もとのデータは上書かれる。
*
* @param buf 文字列バッファ
* @param str 設定する文字列
* @return 正常:0, エラー:-1
*/
int CmnStringBuffer_Set(CmnStringBuffer *buf, const char *str)
{
size_t strLen;
strLen = strlen(str);
/* 文字列を設定 */
if (CmnDataBuffer_Set(buf->_buf, str, strLen + 1) != 0) {
return -1;
}
buf->string = buf->_buf->data;
buf->length = strLen;
return 0;
}
CmnStringBuffer_Append : 文字列追加
現在設定されている文字列の末尾に、引数strの文字列を追加します。内部的には CmnDataBuffer を使っており、バッファの拡張は CmnDataBuffer が行っています。
/**
* @brief 文字列バッファへのデータ追加
*
* 文字列バッファの末尾にデータを追加する。
*
* @param buf 文字列バッファ
* @param str 追加する文字列
* @return 正常:0, エラー:-1
*/
int CmnStringBuffer_Append(CmnStringBuffer *buf, const char *str)
{
size_t strLen;
strLen = strlen(str);
/* '\0'を削除 */
CmnDataBuffer_Delete(buf->_buf, 1);
/* 文字列を追加 */
if (CmnDataBuffer_Append(buf->_buf, str, strLen + 1) != 0) {
return -1;
}
buf->string = buf->_buf->data;
buf->length += strLen;
return 0;
}
CmnStringBuffer_Free : 文字列バッファ破棄
文字列バッファを破棄してメモリを解放します。
/**
* @brief 文字列バッファの解放
*
* 文字列バッファが不要になった場合、メモリ解放のために必ず本関数を呼び出すこと。
*
* @param buf 文字列バッファ
*/
void CmnStringBuffer_Free(CmnStringBuffer *buf)
{
free(buf->_buf);
free(buf);
}
コメント