如何让用户在C中指定多维数组的大小

时间:2022-09-06 14:17:14

Just like the title says. Is there anyway to allow the user to specify both parameters of a 2 dimensional array in C? The array will be called to a function and changed within the function.

就像标题所说的那样。反正是否允许用户在C中指定二维数组的两个参数?该数组将被调用到函数并在函数内更改。

Functions require at least the second parameter for the size of an array, and I don't want to specify an arbitrary large number for the size of the array.

函数至少需要第二个参数来表示数组的大小,我不想为数组的大小指定任意大数。

I should point out that I am a very new C programmer, and I know little about C in general. Don't be offended if you expose me to an entirely new concept and I ask a ton of questions about it!

我应该指出,我是一个非常新的C程序员,我对C一般都知之甚少。如果你让我接触到一个全新的概念,请不要被冒犯,我问了很多关于它的问题!

3 个解决方案

#1


1  

Yes, since C99 you can write:

是的,因为C99你可以写:

void func(int rows, int cols, int array[rows][cols])
{
// stuff...
}

and call it:

并称之为:

int main()
{
    int c = rand() % 10 + 1;
    int arr1[6][c];  func(6, c, arr1);
    int arr2[9][3]; func(9, 3, arr2);

    size_t large = 100000000;
    int (*arr3)[c] = malloc(sizeof(int[large][c]));
    func(large, c, arr3);
    free(arr3);
}

In C11 this feature was marked "optional" for political reasons, however all compilers except MSVC support it.

在C11中,出于政治原因,此功能被标记为“可选”,但除了MSVC之外的所有编译器都支持它。

#2


1  

This demonstrates VLAs (variable length arrays) at work. It is based on code for SO 32565694, which asked about VLAs in structures. This code avoids using structures.

这表明VGA(可变长度阵列)在工作。它基于SO 32565694的代码,该代码询问结构中的VLA。此代码避免使用结构。

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

typedef struct
{
    int nr, nc;
    void *data;     // Actually double a[nr][nc]
} Matrix;

static double variant1(int nr, int nc, int r, int c)
{
    assert(nr != 0);
    return (r * nc) + c + 1;
}

static double variant2(int nr, int nc, int r, int c)
{
    return ((nr - r) * nc) + (nc - c) + 1;
}

typedef double (*Initializer)(int nr, int nc, int r, int c);

static void mat_init(int nr, int nc, double m[nr][nc], Initializer init)
{
    assert(m != 0 && nr > 0 && nc > 0);
    printf("Set: [%dx%d]\n", nr, nc);
    for (int i = 0; i < nr; i++)
    {
        printf("[%d]:", i);
        for (int j = 0; j < nc; j++)
        {
            double v = init(nr, nc, i, j);
            m[i][j] = v;
            printf(" %6.1f", v);
        }
        putchar('\n');
    }
}

static void mat_dump(const char *tag, int nr, int nc, double m[nr][nc])
{
    assert(m != 0 && nr > 0 && nc > 0);
    printf("Matrix %s: %dx%d\n", tag, nr, nc);
    for (int i = 0; i < nr; i++)
    {
        printf("[%d]:", i);
        for (int j = 0; j < nc; j++)
            printf(" %6.1f", m[i][j]);
        putchar('\n');
    }
}

static void mat_multiply(int r1, int c1, double m1[r1][c1],
                         int r2, int c2, double m2[r2][c2],
                         int r3, int c3, double m3[r3][c3])
{
    assert(r1 > 0 && c1 > 0 && r2 > 0 && c2 > 0 && r3 > 0 && c3 > 0);
    printf("m1[%d][%d] x m2[%d][%d] = m3[%d][%d]\n", r1, c1, r2, c2, r3, c3);
    assert(r1 == r3 && c2 == c3 && c1 == r2);

    for (int i = 0; i < r1; i++)
    {
        for (int j = 0; j < c2; j++)
        {
            double sum = 0.0;
            for (int k = 0; k < c1; k++)
                sum += m1[i][k] * m2[k][j];
            m3[i][j] = sum;
        }
    }
}

int main(void)
{
    int r1 = 3;
    int c1 = 5;
    int r2 = c1;
    int c2 = 4;
    int r3 = r1;
    int c3 = c2;

    double m1[r1][c1];
    double m2[r2][c2];
    double m3[r3][c3];

    printf("m1:\n");
    mat_init(r1, c1, m1, variant1);
    printf("m2:\n");
    mat_init(r2, c2, m2, variant2);

    mat_dump("m1", r1, c1, m1);
    mat_dump("m2", r2, c2, m2);
    mat_multiply(r1, c1, m1, r2, c2, m2, r3, c3, m3);
    mat_dump("m3", r3, c3, m3);

    return 0;
}

Example output:

输出示例:

m1:
Set: [3x5]
[0]:    1.0    2.0    3.0    4.0    5.0
[1]:    6.0    7.0    8.0    9.0   10.0
[2]:   11.0   12.0   13.0   14.0   15.0
m2:
Set: [5x4]
[0]:   25.0   24.0   23.0   22.0
[1]:   21.0   20.0   19.0   18.0
[2]:   17.0   16.0   15.0   14.0
[3]:   13.0   12.0   11.0   10.0
[4]:    9.0    8.0    7.0    6.0
Matrix m1: 3x5
[0]:    1.0    2.0    3.0    4.0    5.0
[1]:    6.0    7.0    8.0    9.0   10.0
[2]:   11.0   12.0   13.0   14.0   15.0
Matrix m2: 5x4
[0]:   25.0   24.0   23.0   22.0
[1]:   21.0   20.0   19.0   18.0
[2]:   17.0   16.0   15.0   14.0
[3]:   13.0   12.0   11.0   10.0
[4]:    9.0    8.0    7.0    6.0
m1[3][5] x m2[5][4] = m3[3][4]
Matrix m3: 3x4
[0]:  215.0  200.0  185.0  170.0
[1]:  640.0  600.0  560.0  520.0
[2]: 1065.0 1000.0  935.0  870.0

It would be perfectly feasible to use command line arguments or user input to set the values of r1, c1 (or r2) and c2 (but the values in r2 (or c1), r3 and c3 are constrained, for this code, by r1, c1 and c2). The initialization code would work fine, and so would the multiplication.

使用命令行参数或用户输入来设置r1,c1(或r2)和c2的值是完全可行的(但是对于此代码,r2(或c1),r3和c3中的值受到r1约束,c1和c2)。初始化代码可以正常工作,乘法也是如此。

#3


0  

When declaring array the size should be known by compile time. In order to do what you ask you should use dynamic allocation, like malloc.

声明数组时,编译时应知道大小。为了做你所要求的,你应该使用动态分配,比如malloc。

You can read an int from user, and then call malloc with that size for a multidimensional array

您可以从用户读取一个int,然后为该多维数组调用具有该大小的malloc

#1


1  

Yes, since C99 you can write:

是的,因为C99你可以写:

void func(int rows, int cols, int array[rows][cols])
{
// stuff...
}

and call it:

并称之为:

int main()
{
    int c = rand() % 10 + 1;
    int arr1[6][c];  func(6, c, arr1);
    int arr2[9][3]; func(9, 3, arr2);

    size_t large = 100000000;
    int (*arr3)[c] = malloc(sizeof(int[large][c]));
    func(large, c, arr3);
    free(arr3);
}

In C11 this feature was marked "optional" for political reasons, however all compilers except MSVC support it.

在C11中,出于政治原因,此功能被标记为“可选”,但除了MSVC之外的所有编译器都支持它。

#2


1  

This demonstrates VLAs (variable length arrays) at work. It is based on code for SO 32565694, which asked about VLAs in structures. This code avoids using structures.

这表明VGA(可变长度阵列)在工作。它基于SO 32565694的代码,该代码询问结构中的VLA。此代码避免使用结构。

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

typedef struct
{
    int nr, nc;
    void *data;     // Actually double a[nr][nc]
} Matrix;

static double variant1(int nr, int nc, int r, int c)
{
    assert(nr != 0);
    return (r * nc) + c + 1;
}

static double variant2(int nr, int nc, int r, int c)
{
    return ((nr - r) * nc) + (nc - c) + 1;
}

typedef double (*Initializer)(int nr, int nc, int r, int c);

static void mat_init(int nr, int nc, double m[nr][nc], Initializer init)
{
    assert(m != 0 && nr > 0 && nc > 0);
    printf("Set: [%dx%d]\n", nr, nc);
    for (int i = 0; i < nr; i++)
    {
        printf("[%d]:", i);
        for (int j = 0; j < nc; j++)
        {
            double v = init(nr, nc, i, j);
            m[i][j] = v;
            printf(" %6.1f", v);
        }
        putchar('\n');
    }
}

static void mat_dump(const char *tag, int nr, int nc, double m[nr][nc])
{
    assert(m != 0 && nr > 0 && nc > 0);
    printf("Matrix %s: %dx%d\n", tag, nr, nc);
    for (int i = 0; i < nr; i++)
    {
        printf("[%d]:", i);
        for (int j = 0; j < nc; j++)
            printf(" %6.1f", m[i][j]);
        putchar('\n');
    }
}

static void mat_multiply(int r1, int c1, double m1[r1][c1],
                         int r2, int c2, double m2[r2][c2],
                         int r3, int c3, double m3[r3][c3])
{
    assert(r1 > 0 && c1 > 0 && r2 > 0 && c2 > 0 && r3 > 0 && c3 > 0);
    printf("m1[%d][%d] x m2[%d][%d] = m3[%d][%d]\n", r1, c1, r2, c2, r3, c3);
    assert(r1 == r3 && c2 == c3 && c1 == r2);

    for (int i = 0; i < r1; i++)
    {
        for (int j = 0; j < c2; j++)
        {
            double sum = 0.0;
            for (int k = 0; k < c1; k++)
                sum += m1[i][k] * m2[k][j];
            m3[i][j] = sum;
        }
    }
}

int main(void)
{
    int r1 = 3;
    int c1 = 5;
    int r2 = c1;
    int c2 = 4;
    int r3 = r1;
    int c3 = c2;

    double m1[r1][c1];
    double m2[r2][c2];
    double m3[r3][c3];

    printf("m1:\n");
    mat_init(r1, c1, m1, variant1);
    printf("m2:\n");
    mat_init(r2, c2, m2, variant2);

    mat_dump("m1", r1, c1, m1);
    mat_dump("m2", r2, c2, m2);
    mat_multiply(r1, c1, m1, r2, c2, m2, r3, c3, m3);
    mat_dump("m3", r3, c3, m3);

    return 0;
}

Example output:

输出示例:

m1:
Set: [3x5]
[0]:    1.0    2.0    3.0    4.0    5.0
[1]:    6.0    7.0    8.0    9.0   10.0
[2]:   11.0   12.0   13.0   14.0   15.0
m2:
Set: [5x4]
[0]:   25.0   24.0   23.0   22.0
[1]:   21.0   20.0   19.0   18.0
[2]:   17.0   16.0   15.0   14.0
[3]:   13.0   12.0   11.0   10.0
[4]:    9.0    8.0    7.0    6.0
Matrix m1: 3x5
[0]:    1.0    2.0    3.0    4.0    5.0
[1]:    6.0    7.0    8.0    9.0   10.0
[2]:   11.0   12.0   13.0   14.0   15.0
Matrix m2: 5x4
[0]:   25.0   24.0   23.0   22.0
[1]:   21.0   20.0   19.0   18.0
[2]:   17.0   16.0   15.0   14.0
[3]:   13.0   12.0   11.0   10.0
[4]:    9.0    8.0    7.0    6.0
m1[3][5] x m2[5][4] = m3[3][4]
Matrix m3: 3x4
[0]:  215.0  200.0  185.0  170.0
[1]:  640.0  600.0  560.0  520.0
[2]: 1065.0 1000.0  935.0  870.0

It would be perfectly feasible to use command line arguments or user input to set the values of r1, c1 (or r2) and c2 (but the values in r2 (or c1), r3 and c3 are constrained, for this code, by r1, c1 and c2). The initialization code would work fine, and so would the multiplication.

使用命令行参数或用户输入来设置r1,c1(或r2)和c2的值是完全可行的(但是对于此代码,r2(或c1),r3和c3中的值受到r1约束,c1和c2)。初始化代码可以正常工作,乘法也是如此。

#3


0  

When declaring array the size should be known by compile time. In order to do what you ask you should use dynamic allocation, like malloc.

声明数组时,编译时应知道大小。为了做你所要求的,你应该使用动态分配,比如malloc。

You can read an int from user, and then call malloc with that size for a multidimensional array

您可以从用户读取一个int,然后为该多维数组调用具有该大小的malloc