C Passing Pointer to Pointer to a Function and Using malloc

后端 未结 1 387
梦毁少年i
梦毁少年i 2021-01-27 01:30

I\'m trying to get std input to scan in two 2d parallel arrays (arrAtk, arrDef) of x rows (x<100), and y columns (y<1,000,000). But y is a varia

相关标签:
1条回答
  • 2021-01-27 02:19

    While there are better ways of doing this, it can be done with the approach you have taken. The first thing to note is you were passing each pointer to your function instead of the address of the pointer. When that occurs, your function receives a copy of the pointer, containing the proper address for the values (if initialized), but with a very different address of its own.

    So when you allocate storage for each of your arrays in the function, the pointers in main are completely unchanged. They still point to nothing. In order to have the allocations reflected in main you must pass the address of the pointer to your function, and dereference accordingly in your function, so that the allocations are available in main.

    The short version is you need to call your function with scanIn (&arrAtk, &arrDef, &armies) and your prototype must be (int***, int***, int**). (not particularly attractive)

    One other issue is that style in C generally avoids the use of caMelCase variables (leave that for C++). See: (section 2.2) NASA C Style Guide (Goddard Spaceflight Center 1994)

    Below is an example of the additional level of indirection required to make the allocation work as you intended. (note: you should also free the memory you allocate):

    #include <stdio.h>
    #include <stdlib.h>
    
    int scan_in (int***, int***, int**);
    
    int main (void) {
    
        int cases, *armies, **arr_atk, **arr_def;
    
        cases = scan_in (&arr_atk, &arr_def, &armies);
    
        printf ("\n cases         : %d\n", cases);
        printf (" arr_atk[1][2] : %d\n", arr_atk[1][2]);
        printf (" arr_def[0][1] : %d\n\n", arr_def[0][1]);
    
        return 0;
    }
    
    int scan_in (int ***arr_atk, int ***arr_def, int **armies)
    {    
        int i, j, cases;
    
        scanf ("%d",&cases);
        *arr_atk = malloc (sizeof **arr_atk * cases);
        *arr_def = malloc (sizeof **arr_def * cases);
        *armies = malloc (sizeof *armies * cases);
    
        for (i = 0; i < cases; i++) {
            scanf ("%d", &(*armies)[i]);
            (*arr_atk)[i] = malloc (sizeof ***arr_atk * (*armies)[i]);
            (*arr_def)[i] = malloc (sizeof ***arr_def * (*armies)[i]);
    
            for (j = 0; j < (*armies)[i]; j++) {
                scanf ("%d", &(*arr_atk)[i][j]);
            }
            for (j = 0; j < (*armies)[i]; j++) {
                scanf ("%d", &(*arr_def)[i][j]);
            }
        }
        return (cases);
    }
    

    Input

    $ cat ../dat/2dscan.txt
    2
    2
    3
    6
    5
    2
    3
    2
    3
    12
    9
    3
    4
    

    Output

    $ ./bin/2dscanin < ../dat/2dscan.txt
    
     cases         : 2
     arr_atk[1][2] : 12
     arr_def[0][1] : 2
    

    note: since you are new to C, there are a few more areas where you can improve your code: (1) always initialize your variables that are not explicitly assigned a value in your code; (2) always validate the return values from the functions you call; and (3) always keep track of, and free the memory you allocate when it is no longer needed. Taking that into consideration, your main and scan_in code would look like:

    int main (void) {
    
        int i, cases = 0, *armies = NULL, **arr_atk = {NULL}, **arr_def = {NULL};
    
        if ((cases = scan_in (&arr_atk, &arr_def, &armies)) < 1) {
            fprintf (stderr, "error: invalid value for cases returned.\n");
            return 1;
        }
    
        printf ("\n cases         : %d\n", cases);
        printf (" arr_atk[1][2] : %d\n", arr_atk[1][2]);
        printf (" arr_def[0][1] : %d\n\n", arr_def[0][1]);
    
        for (i = 0; i < cases; i++) { /* free allocated memory */
            if (arr_atk[i]) free (arr_atk[i]);
            if (arr_def[i]) free (arr_def[i]);
        }
        if (arr_atk) free (arr_atk);
        if (arr_def) free (arr_def);
        if (armies)  free (armies);
    
        return 0;
    }
    
    int scan_in (int ***arr_atk, int ***arr_def, int **armies)
    {    
        int i, j, cases;
    
        if (scanf ("%d",&cases) != 1) {
            fprintf (stderr, "scan_in() error: input failure.\n");
            return 0;
        }
        *arr_atk = malloc (sizeof **arr_atk * cases);
        *arr_def = malloc (sizeof **arr_def * cases);
        *armies = malloc (sizeof *armies * cases);
    
        for (i = 0; i < cases; i++) {
            if (scanf ("%d", &(*armies)[i]) != 1) {
                fprintf (stderr, "scan_in() error: input failure.\n");
                return 0;
            }
            (*arr_atk)[i] = malloc (sizeof ***arr_atk * (*armies)[i]);
            (*arr_def)[i] = malloc (sizeof ***arr_def * (*armies)[i]);
    
            for (j = 0; j < (*armies)[i]; j++) {
                if (scanf ("%d", &(*arr_atk)[i][j]) != 1) {
                    fprintf (stderr, "scan_in() error: input failure.\n");
                    return 0;
                }
            }
            for (j = 0; j < (*armies)[i]; j++) {
                if (scanf ("%d", &(*arr_def)[i][j]) != 1) {
                    fprintf (stderr, "scan_in() error: input failure.\n");
                    return 0;
                }
            }
        }
        return (cases);
    }
    
    0 讨论(0)
提交回复
热议问题