首页 文章

C将指针传递给指向函数的指针并使用malloc

提问于
浏览
1

我试图获得std输入来扫描x行(x <100)和y列(y <1,000,000)的两个2d并行数组(arrAtk,arrDef) . 但y是每行中的可变长度 .

输入的第一行是x,表示每个数组中的行数 . 第二行是y表示第一行中的列数 . 接下来是y整数被读入arrAtk数组 . 然后另一个y整数被读入arrDef数组 . 直接跟随是下一行中列数的int y . 等等 .

并行数组将保存将在稍后排序的整数,并且将比较每个并行元素以查看哪些行具有更高的数字 .

Problem: So I'm trying to scan the input with a function call and dynamically allocate the correct amount of memory and scan the input for each row of the 2d arrays. This seems to work okay but then when I try to print the array values in main it crashes. The printf statements work in the scanIn function so I must not be passing values correctly. How can I get it to where I can use the dynamically created arrays outside of the function?

Thanks in advance

标准输入示例:

2  //<- x num of rows 
2  //<- y num of cols
3 
6
5
2
3  //<- y num of cols
2
3
12
9
3
4

码:

#include <stdio.h>
#include <stdlib.h>

int scanIn(int**,int**,int*);

int main(){
    int cases, *armies, **arrAtk, **arrDef;

    cases = scanIn(arrAtk,arrDef,armies);

    printf("%d\n",arrAtk[1][2]); // Should be 12 with above input
    printf("%d",arrDef[0][1]);   // Should be 2

    return 0;
}

int scanIn(int **arrAtk, int **arrDef, int *armies){
    int i, j, cases;

    scanf("%d",&cases);
    arrAtk = (int**)malloc(sizeof(int*)*cases);
    arrDef = (int**)malloc(sizeof(int*)*cases);
    armies = (int*)malloc(sizeof(int)*cases);

    for(i=0;i<cases;i++){
        scanf("%d",&armies[i]);
        arrAtk[i] = malloc(sizeof(int)*armies[i]);
        arrDef[i] = malloc(sizeof(int)*armies[i]);

        for(j=0;j<armies[i];j++){
            scanf("%d",&arrAtk[i][j]);
        }
        for(j=0;j<armies[i];j++){
            scanf("%d",&arrDef[i][j]);
        }
    }
    return (cases);
}

1 回答

  • 1

    虽然有更好的方法可以做到这一点,但可以采用您采用的方法 . 首先要注意的是,您将每个指针传递给函数而不是指针的地址 . 当发生这种情况时,您的函数会收到指针的副本,其中包含值的正确地址(如果已初始化),但具有自己的非常不同的地址 .

    因此,当您为函数中的每个数组分配存储时, main 中的指针完全不变 . 他们仍然没有任何意义 . 为了使分配反映在 main 中,您必须将指针的地址传递给您的函数,并在函数中相应地取消引用,以便在 main 中提供分配 .

    简短的版本是你需要用 scanIn (&arrAtk, &arrDef, &armies) 调用你的函数,你的原型必须是 (int***, int***, int**) . (不是特别有吸引力)

    另一个问题是C中的样式通常避免使用 caMelCase 变量(留给C表示) . 见:(第2.2节)NASA C Style Guide(Goddard Spaceflight Center 1994)

    下面是使分配按预期工作所需的额外间接级别的示例 . (注意:你还应该释放你分配的内存):

    #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: 因为您是C新手,所以还有一些领域可以改进代码: (1) 始终初始化未在代码中明确赋值的变量; (2) 始终验证您调用的函数的返回值;和 (3) 始终跟踪,并且 free 在不再需要时分配的内存 . 考虑到这一点,您的 mainscan_in 代码将如下所示:

    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);
    }
    

相关问题