8

だから私はにを追加しようとしてcharいますchar*

たとえば、char *word = " "; 私も持っていますchar ch = 'x';

私はappend(word, ch);この方法を使用しています。

void append(char* s, char c)
{

    int len = strlen(s);
    s[len] = c;
    s[len+1] = '\0';
}

それは私にセグメンテーション違反を与えます、そして私はなぜ私が推測するのか理解しています。範囲外だからs[len]です。それが機能するようにするにはどうすればよいですか?char*char word [500]のようなものを使用する場合は、多くのこともクリアする必要があります。いくつかの文字が追加されたら、どうすればクリアできますか?それはstrlenいつもそう500だろうか?前もって感謝します。

4

5 に答える 5

11

典型的なCの練習は次のようになります:

//returns 1 if failed, 0 if succeeded 
int  append(char*s, size_t size, char c) {
     if(strlen(s) + 1 >= size) {
          return 1;
     }
     int len = strlen(s);
     s[len] = c;
     s[len+1] = '\0';
     return 0;
}

関数を渡すとき、関数を変更する配列は、コンパイル時にどのくらいのスペースがあるかわかりません。Cでの通常の方法は、配列の長さも渡すことです。関数はこの境界を信頼し、関数が持っているスペースで作業を実行できない場合は失敗します。もう1つのオプションは、新しい配列を再割り当てして返すことです。返すchar*char**入力として受け取る必要がありますが、この状況でヒープメモリを管理する方法を慎重に検討する必要があります。しかし、再割り当てせずに、はい、スペースが残っていないときに追加するように求められた場合、関数はどういうわけか失敗する必要があります。失敗する方法はあなた次第です。

于 2012-10-17T16:56:47.663 に答える
5

Cのインプレース文字列に追加するのは難しいです。次のようにしてみてください。

char *append(const char *s, char c) {
    int len = strlen(s);
    char buf[len+2];
    strcpy(buf, s);
    buf[len] = c;
    buf[len + 1] = 0;
    return strdup(buf);
}

終了したら、返された文字列の割り当てを解除してください。

参考:渡した文字列が読み取り専用メモリに保存されているためか、セグフォールトが発生します。しかし、あなたは正しいです、あなたはまた、最後から書き留めています([len+1]書き込みではなく、書き込み[len])。

于 2012-10-17T16:57:36.043 に答える
3

あなたが通過している場合

append("foo", 'X');

fooは通常読み取り専用ストレージに配置されるため、クラッシュします。そうでない場合でも、おそらく何か悪いものを上書きします!この場合、コンパイラは、constchar*からchar*への変換を警告する必要があります。これが手がかりになります。

于 2012-10-17T16:55:29.050 に答える
0

はい、あなたが行った仮定は-ほぼ-正しい-文字列の境界を超えて書き込もうとしていることが原因である可能性があります(実際にはまだ有効な場所s[strlen(s) + 1]であるため、範囲外です-終了するNULバイトが保存されますs[strlen(s)]そこの)。ただし、文字列リテラルは通常、プロセスメモリの読み取り専用部分にあるため、変更することもできません。これらのアクションは両方とも、クラッシュする可能性のある未定義の動作の呼び出しにつながります。この問題は、動的に割り当てられたストレージに文字列をコピーしてから、そのコピーを変更することで解決できます。また、読み取り専用の文字列を渡すことができないことを示唆しているconst char *ため、関数の引数で使用することになっています。char *

char *append(const char *orig, char c)
{
    size_t sz = strlen(orig);
    char *str = malloc(sz + 2);
    strcpy(str, orig);
    str[sz] = c;
    str[sz + 1] = '\0';
    return str;
}

free()また、必要がなくなったときに返される文字列を忘れないでください。

于 2012-10-17T17:01:00.740 に答える
0

第一に、文字列定数は読み取り専用メモリにある傾向があるため、任意の文字列に安全に追加することはできません。そのため、文字列に書き込もうとすると、セグメンテーション違反が発生する可能性があります。彼らはあなたがそれの終わりを越えて撃たなかったバッファをあなたに渡しました。

特に、charx[500]を実行する場合。

strlen(x)が500を返すという保証はありません。これは、xの先頭からnullに達するまでにカウントする必要のある文字数を返します。xの内容によっては、0、1 ... 500、501...が返される場合があります。

実際には、追加するバッファのサイズを指定してappendを呼び出すか(バッファがいっぱいの場合は適切な処理を実行できます)、呼び出されるたびにappendに新しいバッファを割り当てさせます。この場合は次のようになります。もちろん、バッファを再度解放する必要があります。

于 2012-10-17T17:02:29.380 に答える