2

以下はプログラムの関数です。

//read the specified file and check for the input ssn
int readfile(FILE *fptr, PERSON **rptr){
    int v=0, i, j;
    char n2[MAXS+1], b[1]=" ";

    for(i=0; i<MAXR; i++){
        j=i;
        if(fscanf(fptr, "%c\n%d\n%19s %19s\n%d\n%19s\n%d\n%19s\n%19s\n%d\n%d\n%19s\n\n",
                    &rptr[j]->gender, &rptr[j]->ssn, rptr[j]->name, n2, &rptr[j]->age, 
                    rptr[j]->job, &rptr[j]->income, rptr[j]->major, rptr[j]->minor,
                    &rptr[j]->height, &rptr[j]->weight, rptr[j]->religion)==EOF) {
            i=MAXR;
        }
        strcat(rptr[j]->name, b);
        //strcat(rptr[j]->name, n2);
        if(&rptr[MAXR]->ssn==&rptr[j]->ssn)
            v=j;
    }
    return v;
}

コメントされた行はそのようなものです。なぜなら、割り当てが明らかに不足しているにもかかわらず、何らかの理由で配列'b'に文字列'n2'が含まれているためです。これは、最初のstrcat呼び出しの前ですが、fscanf呼び出しの後/最中に発生します。

目的の目標を達成しますが、特にbに1つの配列要素用の予約スペースしかない場合にn2がbの末尾に連結されるのはなぜですか?

fscanf呼び出し後の変数定義のスニペットは次のとおりです。

*rptr[j]->name = "Rob"

b = " Low"

n2= "Low"
4

2 に答える 2

3

あなたが幸運になったので、それはうまくいきます。 bたまたまメモリ内でn2正しい順序で隣り合っていました。Cは配列の境界チェックを行わないため、非常に喜んで配列をオーバーフローさせることができます。したがって、次のように配列を宣言できます。

char someArray[1] = "lots and lots of characters";

someArrayCコンパイラ(確かに古いもの)は、その数の文字を格納するのに十分なスペースが明らかにない場合でも、これで問題ないと考えます。この状況で何をするかが定義されているかどうかはわかりませんが(おそらくそうではないと思います)、私のコンパイラでは、人口を配列のサイズに制限しているため、境界をオーバーフローしません(someArray=={'l'})。

あなたの状況は同じです(それほど極端ではありませんが)。 char b[1]1バイトを格納するのに十分なスペースのある配列を作成しています。そのバイトにスペースを入れているので、ヌルターミネータの余地はありません。 strcat、nullターミネータに到達するまでメモリをコピーし続けます。その結果、次の文字列の終わりまでではなくても、ターミネータが見つかるまでメモリをコピーし続けます(これがあなたの場合に起こっていることです)。

C ++コンパイラを使用していた場合は、配列に多くの項目を入れようとしていることを通知するために、少なくとも警告(またはエラーの可能性が高い)がスローされます。

于 2011-05-23T14:37:41.253 に答える
2

Bはサイズ2である必要があります。スペースの場合は1、ヌルの場合は1です。

于 2011-05-23T14:14:12.533 に答える