1

const char * s [0]、s [1]、...s[n-1]をCの1つの長いcharout[]に連結したいとします。

正式には(簡単にするために、バッファオーバーランを無視します):

void concatManyStrings(char out[], const char *s[], size_t n);


もちろん、これは簡単な作業です。outへのポインタから始めて、入力文字列をループしながら 、charごとにそれを進めます。

別のアプローチ(まだ線形時間です)は、最後へのポインターを保持することで
あり、各s[i]で次のことを行います。

{ strcpy(endp, s[i]); endp += strlen(s[i]); }

ただし、その方法を知っている標準のCRT関数があり、コピーされた文字の数(または同等に、コピーされた後の次の文字へのポインター)を返す場合、コードはよりクリーンになりstrcpy()ます

私が考えることができる唯一のCRT関数はそれを実行しますが、カウントを返す 単純な関数ほど効率的sprintf()ではないことは明らかです。
strcpy()

私が欠けているような機能はありますか?

4

3 に答える 3

2

strlcpy()strlcat()残念ながら非標準ですが、たまたまそれらを持っている場合は、これを使用できます。どちらも、コピーされた文字列の末尾を特定できる結果を返します。 とは異なりstrcpy()strcat()(やや役に立たない) コピー先の先頭へのポインターを返します。

于 2011-08-25T19:54:55.587 に答える
1

バッファ オーバーランを無視するわけにはいきません。これは、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()ます。これは、ターゲット文字列の最初の文字へのポインターを返すよりもはるかに役立ちます。

私が知っているこれを行うための標準関数はありません。

于 2011-08-25T19:45:44.110 に答える
0

を使用snprintfします。これは基本的に、文字列の組み立てに関するすべての質問に対する正しい答えです。

snprintf(buf, buflen, "%s%s%s", str1, str2, str3);

n残念ながら、これは入力文字列カウントとして「任意」では機能しません。そのためには、独自のforループを書くだけです...

于 2011-08-25T20:12:02.777 に答える