バッファ オーバーランを無視するわけにはいきません。これは、Web の世界が崩壊する主な原因の 1 つです。
示されているデータ構造を考えると、できることには制限があります。関数に渡されるデータの各文字列の長さがデータ構造に含まれていれば、さらに多くのことができます。ただし、それまでは、各文字列の長さを決定し (そして出力バッファーの長さを指定して)、文字列を安全にコピーするように手配する必要があります。コピーするときまでに文字列の長さがわかるので、memmove()
またはを使用memcpy()
してデータを移動できます。長さがわかっているので、ポインターを調整できます。
int concatManyStrings(char *buffer, size_t buflen, const char **data, size_t nitems)
{
assert(buflen > 0);
char *dst = buffer;
char *end = buffer + buflen - 1;
for (size_t i = 0; i < nitems; i++)
{
size_t len = strlen(data[i]);
if (dst + len >= end)
return -1;
memmove(dst, data[i], len);
dst += len;
}
*dst = '\0';
return 0;
}
これにより、各文字列が 2 回スキャンされます。1 回は長さ、もう 1 回はコピーです。strncpy()
ただし、 null パディング動作 (このコンテキストでは悪魔的) のため、使用する余裕はありません。null 終了が保証されないという事実は問題になりません。strcpy()
長さが安全であることがわかるまでは使用できません。これにはstrlen()
. データが文字列へのポインターの単純な配列ではなく、文字列の長さとポインターを含む構造体の配列である場合は、strlen()
回避できます。strcat()
注意して、 orを使用することが実行可能かもしれませんstrncat()
。主な注意点は、2 次動作 (Schlemiel のアルゴリズム) を回避することです。これは、追加された各文字列の終わりを確実に決定することによって実行できます。の場合strncat()
、サイズ パラメータには十分注意してください。strncpy()
サイズとして入るものとは異なります。また、標準関数は最後の文字を配置した文字列の末尾を報告しないため、引き続き使用する必要がある可能性がありstrlen()
ます。これは、ターゲット文字列の最初の文字へのポインターを返すよりもはるかに役立ちます。
私が知っているこれを行うための標準関数はありません。