2016-12-13 16 views
5

私はこの構造体の配列を持っていますが、この関数は配列のポインタへのポインタをとります。元のサイズは2です。したがって、サイズに達するたびに、再割り当てしてサイズを倍増する必要があります。このコードが実行されると、reallocから無効な古いサイズのエラーが発生します。私は間違って何をしていますか?あなたの関数で構造体のポインタへのポインタを持っているとき、どのようにreallocを使いますか?

int PopulateArray(struct Inventory **inv, int *size, FILE *inputFile) { 
    int count = 0; 
    printf("address: %u\n", inv); 
    printf("address: %u\n", **inv); 
    int itemNumber; 
    int quantity; 
    float price; 
    int month; 
    int year; 
    while (fscanf(inputFile, "%i %i %f %i/%i", &itemNumber, 
    &quantity, &price, &month, &year) != EOF) { 
     (*inv)->itemNumber = itemNumber; 
     (*inv)->quantity = quantity; 
     (*inv)->price = price; 
     (*inv)->expDate.month = month; 
     (*inv)->expDate.year = year; 
     printf("count: %i size: %i\n", count, *size); 

     if (count == *size - 1) { 
     inv = realloc(inv, (*size * 2 * sizeof(struct Inventory))); 
     *size *= 2; 
     } 
     inv++; 
     count++; 
    } 
    return count; 
    } 
+1

while(fscanf(...)!= EOF) 'は安全ではありません。 *コンバージョンの*いくつか*が*すべて*ではない場合に何が起こるかを考えてみてください。 – EOF

答えて

4

invは(おそらく)ポインタ変数のアドレスです。その変数の値をreallocに渡します。

*inv = realloc(*inv, (*size * 2 * sizeof(struct Inventory))); 

同じ理由で、inv自体をインクリメントすることは、あなたが期待することはできません。

reallocを使用する必要があるため、countを使用して配列を参照する必要があります。あなたはinvinv++;)を変更しているので

while (fscanf(inputFile, "%i %i %f %i/%i", &itemNumber, 
    &quantity, &price, &month, &year) != EOF) { 
    (*inv)[count].itemNumber = itemNumber; 
    (*inv)[count].quantity = quantity; 
    (*inv)[count].price = price; 
    (*inv)[count].expDate.month = month; 
    (*inv)[count].expDate.year = year; 
    printf("count: %i size: %i\n", count, *size); 

    if (count == *size - 1) { 
    *inv = realloc(*inv, (*size * 2 * sizeof(struct Inventory))); 
    if (*inv == NULL) { 
     perror("realloc failed"); 
     exit(1); 
    } 
    *size *= 2; 
    } 
    count++; 
} 
3

問題が発生します。

渡されたポインタが内のポインタではなく、有効な割り当て済みポインタである場合にのみ、reallocのデータを取得できます。

invデータを保存する必要がありますので、reallocを使用することができます。現在の要素のポインタは、別の変数でなければなりません。

reallocNULLを返していないことを確認してからinvに割り当ててください。そうしないと、元のポインタが失われます。

これはほとんどのミス(もう1つ、古典的なものを隠している間違い1)を逃してしまいました。struct Inventory **タイプを渡しているので、ポインタを変更できるようになりますが、代わりにダブルポインタを修正しています。

あなたは尖った値ではなく、ポインタのアドレスをあなたのreallocをを実行する必要があります。

*inv = realloc(*inv, (*size * 2 * sizeof(struct Inventory))); 
0

あなたはrealloc()からinvを更新すると、あなたのinvは今、新たにリサイズ配列の開始を指します。だから、あなたのコード

if (count == *size - 1) { 
    inv = realloc(inv, (*size * 2 * sizeof(struct Inventory*))); 
    *size *= 2; 
    } 
    inv++; 

最後inv++inv[1]に効果的invポイントを作るだろう、ではないあなたは、おそらくを指すように望んでいただろうinv[count]

間違った答えが

*inv = realloc(*inv, (*size * 2 * sizeof(struct Inventory))); 

の提案が正しくない

をupvotedされているので、私は下に追加しています。

しようとしているのは、ポインタの配列を動的に倍増させることです。したがって、reallocに渡す正しいポインタタイプはstruct Inventory **です。

(おそらく pptr = malloc(sizeof(struct Inventory*) * INIT_SIZE)によって初期テーブルを作成し、その invがここ reallocのために正しいタイプである)

あなたの機能でreallocを実行した後、元invポインタがと呼ばれるコードで使用される、と述べましたこの関数はもはや有効ではないので、この関数を返すと、サイズ変更された配列へのポインタが失われます。これを処理するには、新しいinvポインタ値を呼び出し関数に戻さなければなりません。

追加編集:

そして実際struct Inventory項目にメモリを割り当てることを忘れないでください:ループの開始時に

inv[count] = malloc(sizeof(struct Inventory)); 

関連する問題