v2.4.0, June 2026
GitHubのプロジェクトページはこちらです。
はじめに
Cプログラム向けの基本的な動的文字列マクロが、uthashの utstring.h に含まれています。自分のCプログラムで使うには、utstring.h をソースディレクトリにコピーし、プログラムで使用するだけです。
#include "utstring.h"動的文字列は、データの挿入、連結、長さと内容の取得、部分文字列の検索、内容の消去などの操作をサポートします。utstringにはバイナリデータも格納できます。文字列の操作を下に示します。
utstringの操作の一部は、マクロではなく関数として実装されています。
ダウンロード
ヘッダーファイル utstring.h をダウンロードするには、https://github.com/troydhanson/uthash のリンクからuthashをクローンするかZIPファイルを取得し、src/ サブディレクトリを確認してください。
BSDライセンス
このソフトウェアは修正版BSDライセンスで提供されています。自由に利用できるオープンソースソフトウェアです。
プラットフォーム
utstring マクロは、次の環境でテストされています。
-
Linux,
-
Windows(Visual Studio 2008およびVisual Studio 2010を使用)
使い方
宣言
動的文字列自体のデータ型は UT_string です。次のように宣言します。
UT_string *str;作成と解放
次に、utstring_new で文字列を作成します。使用を終えたら、utstring_free で文字列とその内容をすべて解放します。
操作方法
utstring_printf または utstring_bincpy の操作で、文字列にデータを挿入(コピー)します。utstringを別のutstringに連結するには utstring_concat を使います。文字列の内容を消去するには utstring_clear を使います。文字列の長さは utstring_len で、内容は utstring_body で取得できます。後者は char* と評価されます。このポインターが指すバッファーは常にヌル終端されています。そのため、文字列を受け取る外部関数に直接渡せます。自動的に付加されるこの終端ヌル文字は、文字列の長さには含まれません。
使用例
次の例でutstringの使い方を示します。
使用例1
#include <stdio.h>
#include "utstring.h"
int main() {
UT_string *s;
utstring_new(s);
utstring_printf(s, "hello world!" );
printf("%s\n", utstring_body(s));
utstring_free(s);
return 0;
}次の例では、utstring_printf が文字列に追記することを示します。連結の例も示しています。
使用例2
#include <stdio.h>
#include "utstring.h"
int main() {
UT_string *s, *t;
utstring_new(s);
utstring_new(t);
utstring_printf(s, "hello " );
utstring_printf(s, "world " );
utstring_printf(t, "hi " );
utstring_printf(t, "there " );
utstring_concat(s, t);
printf("length: %u\n", utstring_len(s));
printf("%s\n", utstring_body(s));
utstring_free(s);
utstring_free(t);
return 0;
}次の例は、文字列にバイナリデータを挿入する方法を示します。また、文字列の内容を消去して、新しいデータを書き込んでいます。
使用例3
#include <stdio.h>
#include "utstring.h"
int main() {
UT_string *s;
char binary[] = "\xff\xff";
utstring_new(s);
utstring_bincpy(s, binary, sizeof(binary));
printf("length is %u\n", utstring_len(s));
utstring_clear(s);
utstring_printf(s,"number %d", 10);
printf("%s\n", utstring_body(s));
utstring_free(s);
return 0;
}リファレンス
以下はutstringの操作です。
操作
|
新しいutstringを割り当てる |
|
sが |
|
割り当て済みのutstringを解放する |
|
utstringを初期化する(構造体自体は割り当てない) |
|
utstringの内部メモリーを解放する(構造体自体は解放しない) |
|
utstringに書式付きで書き込む(追記) |
|
長さlenのバイナリデータを挿入する(追記) |
|
srcのutstringをdstのutstringの末尾に連結する |
|
sの内容を消去する(長さを0にする) |
|
sの長さを符号なし整数として取得する |
|
sの内容への |
|
posから順方向に部分文字列を検索する |
|
posから逆方向に部分文字列を検索する |
new/freeとinit/doneの違い
新しい文字列を割り当てたり解放したりするには、utstring_new と utstring_free を使います。UT_stringを静的に割り当てている場合は、utstring_init と utstring_done で内部メモリーを初期化したり解放したりします。
部分文字列の検索
utstring内の部分文字列を検索するには、utstring_find と utstring_findR を使います。順方向と逆方向の検索が用意されています。逆方向の検索は、文字列の末尾から先頭方向へ走査します。これらは検索開始位置を受け取り、その位置は0(utstringの先頭)を基準に数えます。負の位置は文字列の末尾から数えるため、-1は最後の位置です。逆方向の検索では、開始位置が検索対象の部分文字列の末尾、たとえば cat の t に対応することに注意してください。返り値は常に、utstring内で部分文字列が始まる位置のオフセットを示します。一致する部分文字列が見つからない場合は、-1を返します。
たとえば、s というutstringに次の内容が入っているとします。
ABC ABCDAB ABCDABCDABDEこのとき、ABC を順方向および逆方向に検索すると、次の結果になります。
utstring_find( s, -9, "ABC", 3 ) = 15
utstring_find( s, 3, "ABC", 3 ) = 4
utstring_find( s, 16, "ABC", 3 ) = -1
utstring_findR( s, -9, "ABC", 3 ) = 11
utstring_findR( s, 12, "ABC", 3 ) = 4
utstring_findR( s, 2, "ABC", 3 ) = 0繰り返し使う部分文字列検索
これまでの例は、内部のKnuth-Morris-Pratt(KMP)テーブルを内部で構築し、検索後に解放する「一度だけ使う」部分文字列検索です。ある部分文字列を何度も検索する必要がある場合は、KMPテーブルを保存して再利用する方が効率的です。
KMPテーブルを再利用するには、手動で構築してから内部の検索関数に渡します。使用する関数は次のとおりです。
_utstring_BuildTable (順方向検索用のKMPテーブルを構築する)
_utstring_BuildTableR (逆方向検索用のKMPテーブルを構築する)
_utstring_find (構築済みのKMPテーブルで順方向検索する)
_utstring_findR (構築済みのKMPテーブルで逆方向検索する)次は、部分文字列「ABC」の順方向検索用KMPテーブルを構築し、検索で使う例です。
long *KPM_TABLE, offset;
KPM_TABLE = (long *)malloc( sizeof(long) * (strlen("ABC")) + 1));
_utstring_BuildTable("ABC", 3, KPM_TABLE);
offset = _utstring_find(utstring_body(s), utstring_len(s), "ABC", 3, KPM_TABLE );
free(KPM_TABLE);内部の _utstring_find の第2引数は、開始位置ではなくUT_stringの長さであることに注意してください。文字列の先頭アドレスに位置を加え、その長さから同じ位置を引くことで、位置パラメーターに相当する動作を実現できます。
注意事項
-
メモリー不足時の既定の処理(
exit(-1)を呼び出す動作)を変更するには、utstring_oom()マクロをutstring.hのインクルード前に定義し直してください。たとえば、次のようにします。#define utstring_oom() do { longjmp(error_handling_location); } while (0) ... #include "utstring.h"