2

使用している2つの異なるアレイがあります。1つでは、希望どおりの結果が得られますが、もう1つではそれほど多くはありません。私はこれに似たテキストファイルから読み取ることによって配列をファイリングしています:

2597
283



4
723
21
82
426

最初の5行は顧客IDになります。常に5行ありますが、必ずしも値があるとは限りません。次の行はベンダーの数で、その後にベンダーIDが続きます。

void use_arrays()
{
    int
        i,
        customer_count,
        *customer_ids,
        vendor_count,
        *vendor_ids;

    customer_ids = malloc(sizeof(int));
    vendor_ids = malloc(sizeof(int));
    fill_arrays(&customer_count, customer_ids, &vendor_count, vendor_ids);

    for (i = 0; i < customer_count; i++)
    {
        printf("Customer[%d]: %d\n", i, customer_ids[i]);
    }

    for (i = 0; i < vendor_count; i++)
    {
        printf("Vendor[%d]: %d\n", i, vendor_ids[i]);
    }

    free(customer_ids);
    free(vendor_ids);
}

void fill_arrays(int *customer_count, int *customer_ids, int *vendor_count, int *vendor_ids)
{
    int
        i,
        *temp,
        customer_id,
        vendor_id,
        num_cust = 0;
    FILE
        *inp_file;
    char
        *endptr = NULL,
        buffer[500];

    inp_file = fopen(g_filename, "r");

    for (i = 0; i < 5; i++) /* Can't be more than 5 customers */
    {
        fgets(buffer, sizeof(buffer), inp_file);
        customer_id = strtol(buffer, &endptr, 0);
        if (customer_id != 0)
        {
            customer_ids[i] = customer_id;
        temp = realloc(customer_ids, (i+2)*sizeof(int));
        if (temp != NULL) 
            {
               customer_ids = temp;
            } 
        else 
        {
               printf("Couldn't allocate memory\n");
            }
        num_cust++;
        }
    }
    *customer_count = num_cust;

    /* Next is number of vendor ids*/
    fgets(buffer, sizeof(buffer), inp_file);
    *vendor_count = strtol(buffer, &endptr, 0);

    temp = realloc(vendor_ids, *vendor_count*sizeof(int));
    if (temp != NULL) 
    {
        vendor_ids = temp;
    } 
    else 
    {
        printf("Couldn't allocate memory\n");
    }

    for (i = 0; i < *vendor_count; i++)
    {
        fgets(buffer, sizeof(buffer), inp_file);
        vendor_id = strtol(buffer, &endptr, 0);
        if (vendor_id != 0)
        {
        vendor_ids[i] = vendor_id;
        }
    }
    fclose(inp_file);
}

配列が印刷されると、customer_idsは正しい数値を表示しますがvendor_ids、メモリから乱数を出力します。さらにイライラするのは、ベンダーを内部から正しく印刷することfill_arraysです。

4

2 に答える 2

4

vendor_idsで行う方法を変更する場合fill_arraysは、ポインターへのポインターとして渡す必要があります。

fill_arrays(int *customer_count, int *customer_ids, int *vendor_count, int **vendor_ids)

次のように呼び出します。

fill_arrays(&customer_count, customer_ids, &vendor_count, &vendor_ids);

次に、次のように再割り当てできます。

temp = realloc(*vendor_ids, *vendor_count*sizeof(int));
if (temp != NULL) 
{
    *vendor_ids = temp;
} 

また、関数の最後に:

vendor_ids[i] = vendor_id;

に変更する必要があります

(*vendor_ids)[i] = vendor_id;

にも同じ変更を加える必要がありcustomer_idsます。customer_idsが機能していないのに機能していたという事実vendor_idsは、おそらくrealloc. reallocがメモリ ブロックを新しい場所に再割り当てする必要があると判断した場合、これらの問題が発生しますが、 が同じ場所にメモリを再割り当てした場合、渡したポインタはまだそこを指しています。reallocがその決定を下すかどうかわからないため、 と の両方customer_idsvendor_idsポインターへのポインターとして渡す必要があります。

于 2013-01-22T19:22:05.247 に答える
0

関数からメモリを返す方法が少し混乱しているようです。

このような関数がある場合

void foo(int a);

afoo の内部を変更することはできません。foo は a のコピーのみを取得します。

void foo(int *a);

otoh は foo に a のアドレスを与えます。つまり、「私はあなたが住んでいる場所を知っています」と指定すると、何aを指すかを変更できます。aが配列を指している場合は、その配列の内容を変更できます。単一の整数を指している場合は、それを変更できます。

void foo(int **a);

a何を指すかだけでなく、指す場所も変更できます。aそのため、他の場所を指したい場合はできます。関数で malloc/calloc/realloc を実行して結果を返す場合は、これが必要です。

于 2013-01-22T19:43:38.397 に答える