0

ライブラリ関数 (学校の課題) を使用せずに 2 つの文字列を手動で連結しようとすると、バス エラーが発生します。コードは次のとおりです。

#include <stdio.h>

char *strcattest(char string1[ ], char string2[ ]);

int main() {
    printf("*****STRING CONCATENATION*****\n");
    printf("Hello plus Hello: %s\n", strcattest("Hello","Hello"));
    printf("Hello plus Hellp: %s\n", strcattest("Hello","Hellp"));
    printf("Helo plus Hello: %s\n", strcattest("Helo","Hello"));
    printf("Hello plus Helo: %s\n", strcattest("Hello","Helo"));

    return(0);
}

char *strcattest(char string1[ ], char string2[ ]) {
    int counter = 0;
    while(string1[counter]!='\0') {
        counter++;
    }
    int str2counter = 0;
    while(string2[str2counter]!='\0') {
        string1[counter] = string2[str2counter];
        str2counter++;
        counter++;
    }
    string1[counter]='\0';
    return string1;
}

私はいくつかの調査を行いましたが、これが機能しない理由を概念的に理解していると思います。(静的文字列に基づく変数 string1 を変更しようとして呼び出しています。)ただし、これを修正してそれ自体が動作するようにする方法がわかりません。string1 のコピーとして動作するローカル変数を strcattest 関数に導入しようとしましたが、関数からローカル変数を返すことに対してコンパイラが怒鳴りつけました。

どんな助けでも大歓迎です。ありがとう!

4

4 に答える 4

1

関数に渡す "Hello" 引数は、実際にはプログラムの .data セクションにあります。このセクションを変更することはできません。そうしようとすると、エラーが発生する可能性があります(あなたの場合はバスエラー)。

スタック (ローカル変数と配列) またはヒープ ([mc]alloc() 関数を使用して割り当てられたメモリ) にあるメモリのその部分のみを操作できます。

于 2012-09-18T11:23:43.580 に答える
1

文字列リテラルを別の文字列リテラルに連結しようとしました。これらの文字列リテラルは、短すぎるだけでなく、読み取り専用です。

于 2012-09-18T06:25:43.283 に答える
1

問題:

printf("Hello plus Hello: %s\n", strcattest("Hello","Hello")); 

ここでの文字列"Hello"は文字列リテラルであり、実装定義 (読み取り専用) メモリに配置されます。これらを変更することはできません。変更すると、未定義の動作が発生します。したがって、文字列リテラルを別の文字列リテラルに単純に追加することはできません。これは、変更可能にすることを意図していないためです。

ソリューション:

2 つの文字列リテラルを使用して文字列を取得する場合は、次の手順を実行する必要があります。

  1. 関数に動的に割り当てられたメモリ (malloc) バッファへのポインタを用意します。
  2. このバッファ内に文字列リテラルを追加します。メモリはあなたが所有しているため、内容を変更できます。
  3. この動的に割り当てられたメモリへのポインターを返します。
  4. 返されたポインタの割り当てを解除 (解放) することを忘れないでください。
于 2012-09-18T06:27:37.300 に答える
1

静的(読み取り専用)文字列を変更しようとしているという点で正しいです。これを行うことは、C標準用語の「未定義の動作」です(この場合、クラッシュとして現れます)。

これを修正するには、変更可能な文字配列を割り当てる必要があります。これは、静的 (スタック上) または動的 (を使用malloc) のいずれかで実行できます。

静的に、特定のコンテンツで文字配列を初期化するには、次のことができます

char mystring[1024] = "Hello!";

これにより、文字列の内容で文字配列が初期化され、それらがコピーされます (同様の外観char *mystring = "Hello!";は配列の初期化ではなく、代わりに静的文字列を指すmystringことに注意してください)。その宣言は、グローバル スコープ (関数の外。グローバルを使用する特定の理由がない限り推奨されません) またはmainメソッド内 (その後、 に渡すことができますstrcattest) に配置できます。

動的に、宣言は次のようになります

char *mystring = malloc(1024);

1024文字を保持するのに十分な大きさの初期化されていないバッファを取得します(nullターミネータを数えます)。mallocただし、何かがある場合はfree、後でそれを行う必要があります。そうしないと、メモリリークが発生します。その中に何かを入れるには、

strcpy(mystring, "Hello!");

mystring = "Hello!"この場合は機能しないことに注意してください。

于 2012-09-18T06:31:48.393 に答える