传递任意大小的2D结构数组以在C中起作用

时间:2016-10-14 22:05:24

标签: c arrays struct parameter-passing

我是C的新手。

我有一个二维结构数组,其大小为i,j是在运行时确定的。

我想将此数组作为参数传递给函数并迭代所有元素。

以下是代码的原型:

typedef struct obj {
    char id[10];
    int value;
} Object;

我尝试了以下但是它没有工作:

int sum_all_elements(Object *obj_ptr);

int main() {
    int i, j; //gotten from user input which I omitted

    Object o[i][j];

    int total = sum_all_elements(&o);
}

传递o [i] [j]的正确方法是什么,以及如何在函数中迭代它?

另外,我想创建更新2D数组中元素的函数,有没有一种方法可以在函数中进行更改,并且当我从函数返回时效果仍然存在?

3 个答案:

答案 0 :(得分:1)

使用typedef,如下所示:

enum { IDL = 10 };

typedef struct {
    char id[IDL];
    int value;
} obj;

如果您打算使用2D VLA,那么最好考虑传递第一行的地址,而不是第一行的地址。 (尽管这两个地址是一样的)为什么?将数组(例如obj o[i][j];)作为参数传递给函数时,将第一级间接转换为指针(例如obj o[i][j]变为obj (*o)[j])。

main中声明的VLA为例,如下所示:

    obj o[i][j];    /* declare VLA */

所以你的函数声明需要匹配(并且因为列数是非常量的,所以是正确的顺序)例如:

int sum_all_elements (int i, int j, obj (*obj_ptr)[j]);

然后,您可以在程序中调用该函数,例如:

    printf ("\n sum : %d\n\n", sum_all_elements (i, j, &o[0]));

这相当于:

    printf ("\n sum : %d\n\n", sum_all_elements (i, j, o));

将一个简短示例放在一起(并填充obj[a][b].value = a + b;),您可以执行类似以下操作:

#include <stdio.h>

enum { IDL = 10 };

typedef struct {
    char id[IDL];
    int value;
} obj;

int sum_all_elements (int i, int j, obj (*obj_ptr)[j]);

int main (void) {

    int i, j;

    printf ("\n enter i & j: ");
    if (scanf (" %d %d", &i, &j) != 2) {
        fprintf (stderr, "error: invalid input, i, j.\n");
        return 1;
    }

    obj o[i][j];    /* declare VLA */

    for (int a = 0; a < i; a++)
        for (int b = 0; b < j; b++)
            o[a][b].value = a + b;  /* fill value with misc a + b */

    printf ("\n sum : %d\n\n", sum_all_elements (i, j, o));

    return 0;
}

/* some all .value for i x j array of obj */
int sum_all_elements (int i, int j, obj (*obj_ptr)[j])
{
    int sum = 0;

    for (int a = 0; a < i; a++)
        for (int b = 0; b < j; b++)
            sum += obj_ptr[a][b].value;

    return sum;
}

示例使用/输出

$ ./bin/p2p2a

 enter i & j: 10 10

 sum : 900

答案 1 :(得分:0)

如果您使用的是C99或更高版本,则可以使用VLA来完成此操作。以下示例要求用户输入id结构的valueObject字段的信息,然后调用函数以显示2d VLA的内容:< / p>

#include <stdio.h>

typedef struct obj {
    char id[10];
    int value;
} Object;

void show_obj(int rows, int cols, Object arr[rows][cols]);

int main(void)
{
    int num_rows, num_cols;
    int row, col;

    num_rows = 3;
    num_cols = 3;

    Object obj_arr[num_rows][num_cols];

    for (row = 0; row < num_rows; row++)
        for (col = 0; col < num_cols; col++) {
            printf("Element [%d][%d]:\n", row, col);
            printf("    enter id: ");
            scanf("%9s", obj_arr[row][col].id);
            printf("    enter value: ");
            scanf("%d", &(obj_arr[row][col].value));
        }

    show_obj(num_rows, num_cols, obj_arr);

    return 0;
}

void show_obj(int num_rows, int num_cols, Object obj_arr[num_rows][num_cols])
{
    int row, col;

    for (row = 0; row < num_rows; row++)
        for (col = 0; col < num_cols; col++) {
            printf("Element [%d][%d]:\n", row, col);
            printf("    id: %s\n", obj_arr[row][col].id);
            printf("    value: %d\n", obj_arr[row][col].value);
        }
}

将VLA传递给函数时,请注意必须先传递数组的尺寸。

另一种方法是为结构手动分配内存,然后模拟2d数组。您可以为指向Object结构的指针的多个指针分配空间。这些指针中的每一个都指向一行Object结构的第一个Object,因此您可以在每行中分配空间来存储Object。以下代码演示了第二种方法。设置完成后,obj_arr被访问并传递,就好像它是一个二维数组一样。这种方法的一个缺点是您需要手动释放内存分配。但是,这种方法适用于C99之前的编译器:

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

typedef struct obj {
    char id[10];
    int value;
} Object;

void show_obj(Object **arr, int rows, int cols);

int main(void)
{
    int num_rows, num_cols;
    int row, col;

    num_rows = 3;
    num_cols = 3;

    Object **obj_arr = malloc(sizeof(Object *) * num_rows);

    for (row = 0; row < num_rows; row++)
        obj_arr[row] = malloc(sizeof(Object) * num_cols);

    for (row = 0; row < num_rows; row++)
        for (col = 0; col < num_cols; col++) {
            printf("Element [%d][%d]:\n", row, col);
            printf("    enter id: ");
            scanf("%9s", obj_arr[row][col].id);
            printf("    enter value: ");
            scanf("%d", &(obj_arr[row][col].value));
        }

    show_obj(obj_arr, num_rows, num_cols);

    /* Free allocated memory */
    for (row = 0; row < num_rows; row++)
        free(obj_arr[row]);
    free(obj_arr);       

    return 0;
}

void show_obj(Object **obj_arr, int num_rows, int num_cols)
{
    int row, col;

    for (row = 0; row < num_rows; row++)
        for (col = 0; col < num_cols; col++) {
            printf("Element [%d][%d]:\n", row, col);
            printf("    id: %s\n", obj_arr[row][col].id);
            printf("    value: %d\n", obj_arr[row][col].value);
        }
}

答案 2 :(得分:-2)

你绝对肯定你需要:

我建议使用«linear»数组并通过malloc()(或calloc()分配内存,如果你想在创建时进行零初始化)。这样的事情:

Object *o;
o = (Object*)calloc(i * j, sizeof(Object));

... (doing something with o)

int total = sum_all_elements(o, i, j);

... (now it is time to free the allocated memory)

free(o);
o = 0;

int sum_all_elements(Object *obj_ptr, int i, int j) {
    int x, y, s;
    for (s = y = 0; y < j; y++)
        for (x = 0; x < i; x++) {
            s += obj_ptr[j * y + x].value;
        }
    return s;
}