いくつかの問題...
1.
foo
ここでは定数です。文字列リテラルは変更できません。
2. の契約strcat
は、最初のパラメーターが連結された文字列に適合するのに十分な大きさであることです。より現実的には、これを行うでしょう...
char foo[8] = "foo"; /* Note that buffer size is larger than the string... */
strcat(foo, "bar");
3. ご想像のとおり、これがどのように機能するかは、初心者には明らかではありません。これには理由があると私は言いstrcat
ます。潜在的に任意の長さのバッファーと対話するための優れた C インターフェイスは、これをより明確にします。strncat
またはstrlcat
どのトラックサイズを見たいと思うかもしれません。
一般的に言えば、strcat
ファミリーを使用している場合は、何か間違ったことをしているということです。への各呼び出しstrcat
は、文字列をトラバースして、末尾がどこにあるかを見つける必要があります。これらの操作をたくさん行っていると想像してみてください。O(n) ステップで簡単に実行できる何かが、文字列を繰り返しトラバーサルするために突然 O(n 2 ) になることを想像するのは非常に簡単です。文字列に繰り返し連結する必要がある場合は、文字列の現在の末尾へのポインターを維持し、そこからコピーを行う必要があります。
更新:この最後の提案を行う方法の例は次のとおりです...
struct string
{
char *current_end;
size_t bytes_remaining;
};
int
smart_concat(struct string *str, const char *tail)
{
size_t new_length = strlen(tail);
/* Do we have enough space? (include NUL character) */
if (new_length + 1 < str->bytes_remaining)
{
/* Evidently not... */
return -1;
}
/* Copy the string... (including NUL character) */
memcpy(str->current_end, tail, new_length + 1);
/* Update the pointer to the end of our string, and bytes remaining.. */
str->current_end += new_length;
str->bytes_remaining -= new_length;
return 0;
}
次に、これを次のように使用できます。
struct string str;
char buffer[some_size];
/* Initialize the structure to point at our buffer... */
str.current_end = buffer;
str.bytes_remaining = sizeof(buffer);
/* Strictly speaking, you should check the return code for overflow... */
smart_concat(&str, "foo");
smart_concat(&str, "bar");
/* Print out the result: */
puts(buffer);