1

ファイルから構造体を読み込んでから、表示 (および並べ替え) と配列を試みています。正しいメモリにアクセスしていないことに関係していると思いますが、問題が発生しています。配列を印刷すると、大量の乱数として表示されます。

struct details
{
    int numberOfPresents;
    int numberOfBuildings;
    int buildings[];
};

void print_int_array(const int *array) 
{ 
    for(int i=0; i<200; i++) 
        printf("%d | ", array[i]);

    putchar('\n');
} 

void sort(int buildings[], int count)
{
    int i, j, temp;
    do {
        j = 0;  
        for (i = 0;i<count-1;i++)
        {
            if (buildings[i] < buildings[i+1])
            {
                j = 1;
                temp = buildings[i];
                buildings[i] = buildings[i+1];
                buildings[i+1] = temp;
            }
        }
    } while (j == 1);
}

int main()
{
    FILE *fp;
    fp = fopen("buildings.out", "r");   
    struct details data1;
    size_t structSize = sizeof(struct details);
    //size_t arraySize = sizeof(int)*sizeof(buildings);
    fread(&data1, structSize, 1, fp);
    for(int i=0; i<200; i++) 
        printf("%d | ", data1.buildings[i]);

    //sort(data1.buildings );
    //print_int_array(data1.buildings, arraySize);
    //printf("Number of Houses: %d\n",numberOfHouses(data1.numberOfPresents, data1.buildings));
    fclose(fp);
    return 0;
}
4

2 に答える 2

1

構造体のサイズには、配列の最小限の割り当てのみが含まれます(1つのエントリだと思います)。実際には、必要な200エントリに対して十分な割り当てがありません。いくつかの可能な修正があります。

常に200エントリになる場合は、建物のサイズを200と宣言するだけです。これが最も簡単です。

読む前にエントリの数がわかっている場合は、次のような不快なことを行うことができます(sはエントリの数です)。

struct details *data1 = (struct details *) malloc(sizeof(struct details)+s*sizeof(int));

完了したら、data1を解放します。このタイプのコードは一般的に眉をひそめていますが、以前はかなり一般的でした。読み取りコマンドも複雑になります。

最後のオプションは、建物をint *に変更してから、読み取る前にその配列をmallocすることです。この場合も、読み取りはループで実行する必要があります。

于 2012-12-11T21:30:57.123 に答える
0

データを印刷する際に 2 つの問題があります。

  • レコードに十分なスペースが割り当てられていません。
  • レコードに対して十分なデータが読み取られません。

この行struct details data1は、struct. それらの 200 の十分な必要があります。私はすぐに配列を提案します。

struct details data1[200];

読み取りを実行するとfread(&data1, structSize, 1, fp)、サイズ の 1 つのレコードのみが読み取られますstructSize。200 レコードを読み取るのに十分なメモリが割り当てられたので、読み取るレコードの数を 200 に増やすこともできます。

fread(data1, structSize, 200, fp);

&(今は配列を扱っているため、を削除したことに注意してください。配列を名前で参照すると、配列は自動的にベース アドレスを返します。)

では、ファイルに 200 レコードが含まれていない場合はどうなるでしょうか。fread()実際に読み取ったレコード数を判断するには、おそらく の戻り値を取得する必要があります。

int intNumberOfRecords = fread(&data1, structSize, 200, fp);
for(int i=0; i<intNumberOfRecords ; i++)
  [...]

srtuctこれが機能するようになったので、それ自体をもう少し詳しく見てみましょう。簡単には克服できない定義の課題があります。

struct details{
    int numberOfPresents;
    int numberOfBuildings;
    int buildings[];
};

最後のメンバー はbuildings[]、ファイルから正しく読み取れません。これは、32 ビット メモリ モデルではせいぜい 32 ビット整数にすぎないためです。つまり、ディスクから読み取るのは、メモリ内のどこかを指す 32 ビットの数値にすぎません。最終的に得られないのは、建物を含む配列です。アクセスしようとすると (つまり、sortルーチン内で)、おそらくセグメンテーション フォールトが発生し、プログラムが動作しなくなります。これに対する一般的な解決策を投稿しようとすることは、私の回答の範囲外です。固定サイズの配列を使用するか、可変サイズの配列をディスク (可変長レコード) に動的に書き込む必要があると言えば十分です。固定サイズの配列の方がはるかに簡単です。定義を次のように変更すると、ディスクからいくつかのデータが読み込まれます。

struct details{
    int numberOfPresents;
    int numberOfBuildings;
    int buildings[16];
};

また、セグ フォールトも回避できます。これは良いプラスです。ただし、入力ファイルがどのように見えるかわからないため、データが与えられた場合にこれが機能するかどうかはわかりません。

于 2012-12-11T21:29:01.590 に答える