16

C文字列をコピーする簡単な方法はありますか?

があり、値を取得しconst char *stringAたい( ではないchar *stringBことに注意)。を試してみましたが、それでも同じメモリ位置を指すようになるため、後で変更した場合も同様です。stringBconststringB=(char*) stringAstringBstringAstringB

も試しましたが、十分な大きさの配列に初期化されていないstrcpy(stringB,stringA)場合、セグメンテーション違反があるようです。stringB私はC文字列の経験があまりありませんが、明らかな何かが欠けていますか?

stringBとして初期化するだけの場合char *stringB[23]、文字列よりも長い文字列を持つことは決してないことがわかっているため22(そして null ターミネータを許可する)、それは正しい方法ですか? stringBが他の C 文字列と等しいかどうかチェックされた場合、余分なスペースは何かに影響しますか?

(また、オーバーヘッドを最小限に抑え、個々の文字に簡単にアクセスする必要があるため、文字列を使用するだけでは解決策にはなりません。)

4

4 に答える 4

25

strdup()次のように、C 文字列のコピーを返すために使用できます。

#include <string.h>

const char *stringA = "foo";
char *stringB = NULL;

stringB = strdup(stringA);
/* ... */
free(stringB);    

を使用することもできますstrcpy()が、最初にスペースを割り当てる必要があります。これは難しくありませんが、正しく行わないとオーバーフロー エラーが発生する可能性があります。

#include <string.h>

const char *stringA = "foo";
char *stringB = NULL;

/* you must add one to cover the byte needed for the terminating null character */
stringB = (char *) malloc( strlen(stringA) + 1 ); 
strcpy( stringB, stringA );
/* ... */
free(stringB);

を使用できない場合は、代わりに をstrdup()使用することをお勧めします。この関数は最大 — 最大 —バイトまでしかコピーしないため、オーバーフロー エラーを回避できます。ただし、自分で終了する必要がある場合。しかし、一般的に、必要なサイズは次のようにわかります。strncpy()strcpy()strncpy()nstrlen(stringA) + 1 > nstringB

#include <string.h>

const char *stringA = "foo";
char *stringB = NULL;

/* you must add one to cover the byte needed for the terminating null character */
stringB = (char *) malloc( strlen(stringA) + 1 ); 
strncpy( stringB, stringA, strlen(stringA) + 1 );
/* ... */
free(stringB);

strdup()自身はよりクリーンだと思うので、文字列のみを扱う場合に使用しようとしています。パフォーマンスに関して、POSIX/非 POSIX アプローチに重大な欠点があるかどうかはわかりませんが、私は C または C++ の専門家ではありません。

malloc()toの結果をキャストすることに注意してくださいchar *。これは、あなたの質問が質問としてタグ付けされているためc++です。C++ では、 からの結果をキャストする必要がありmalloc()ます。ただし、C ではこれをキャストしません。

編集

複雑な問題が 1 つありますstrdup()。C または C++ にはありません。したがって、strcpy()orstrncp()を事前にサイズ指定された配列またはmalloc-ed ポインターと共に使用します。のstrncp()代わりにstrcpy()、その関数を使用する場所で使用することをお勧めします。エラーの可能性を減らすのに役立ちます。

于 2012-03-07T00:01:18.060 に答える
4

stringB を char *stringB[23] として初期化すると、文字列が 22 文字を超えることはないとわかっているため (そして null ターミネータを許可する)、それは正しい方法ですか?

ほとんど。C で、文字列が決して長くなりすぎないことが確実にわかっている場合:

char stringB[MAX+1];
assert(strlen(stringA) <= MAX));
strcpy(stringB, stringA);

または、文字列が長すぎる可能性がある場合:

char stringB[MAX+1];
strncpy(stringB, stringA, MAX+1);
if (stringB[MAX] != '\0') {
    // ERROR: stringA was too long.
    stringB[MAX] = '\0'; // if you want to use the truncated string
}

C++ では、std::stringオーバーヘッドが法外であることが証明されていない限り、 を使用する必要があります。多くの実装には、短い文字列の動的割り当てを回避する「短い文字列の最適化」があります。その場合、C スタイルの配列を使用するオーバーヘッドはほとんどまたはまったくありません。個々の文字へのアクセスは、C スタイルの配列と同じくらい便利です。どちらの場合も、s[i]position の文字をlvalueiとして指定します。コピーは、未定義の動作の危険がなくなります。stringB = stringA;

本当に使用できない場合は、固定サイズの配列を含むコピー可能なクラスをstd::string検討してください。std::array<char,MAX+1>

stringB が他の C 文字列と等しいかどうかチェックされた場合、余分なスペースは何かに影響しますか?

を使用するstrcmpと、最短の文字列の最後で停止し、余分なスペースの影響を受けません。

于 2012-03-07T00:24:39.747 に答える
3

純粋な C スタイルで実行する場合は、次のようにします。

char* new_string = strdup(old_string);
free(new_string);

(一種の)C++スタイルでそれをしたい場合:

char* new_string = new char[strlen(old_string) + 1];
strcpy(new_string, old_string);
delete[] new_string;
于 2012-03-07T00:01:40.440 に答える
1

strncpyおそらく、文字列から最初の文字をコピーできる を探しているでしょうn。コピー先の文字列の位置 n に null ターミネータを必ず追加してください。

于 2012-03-07T00:01:41.413 に答える