【问题标题】:How to create a multidimensional array, whose dimension is based on a variable in C?如何创建一个多维数组,其维度基于 C 中的变量?
【发布时间】:2019-07-06 07:25:46
【问题描述】:

基本上,我希望能够在终端中输入维度 n 并创建相应的 n 维数组。

现在我只能创建一个具有相应 n 维数组大小的一维数组。

【问题讨论】:

  • 我不太清楚你在问什么,你想创建一个维数可变的变量吗?那有意义吗?你的用例是什么?
  • 如果你想实现一个维数可变的数组,你必须创建你自己的例程来支持它,至少:一个例程来分配所需的存储空间并初始化用于帮助实现和一个例程,该例程接受有关要访问的元素的信息(可能作为指向索引列表或数组的指针),计算该元素的位置,并返回一个指向它的指针。

标签: c arrays multidimensional-array dynamic


【解决方案1】:

你不能,数组的维数是类型的一部分,所以需要在编译时知道。您可以做一些简单的数学运算,将您想要的内容映射到一维数组。

例子:

设维度 = 3

  • w: 4
  • 小时:8
  • d: 16

代码:

int* data = (int*)malloc(sizeof(int) * w * h * d);
int x = access(1,2,3);  //it will map to location: 1 + 2 * (4) + 3 * (4 * 8)
free(data);


int access(int x, int y, int z){
   return data[x + y * (w) + z * (h * w)];
}

一般的实现可能如下所示

int numDimensions;
printf("Enter number of dimensions:");
scanf("%d", &numDimensions);
int* dimensionSizes = (int*)malloc(sizeof(int) * numDimensions);

//Read each dimension's size
int totalElements = 1;
for(int i = 0; i < numDimensions; ++i){
    printf("Enter size for dimension %d:", i);
    scanf("%d", &dimensionSizes[i]);
    totalElements *= dimensionSizes[i];
}

//allocate 1d array
int* data = (int*) malloc(sizeof(int) * totalElements);

//Read the coordinates you want to store data to
int* position = (int*)malloc(sizeof(int) * numDimensions);
for(int i = 0; i < numDimensions; ++i){
    printf("Enter location in dimension %d:", i);
    scanf("%d", &position[i]);
}

//Read the value you want to store
int value;
printf("Enter value for that position:");
scanf("%d", &value);

//Write the data to the calculated 1d location
data[to1d(position, dimensionSizes, numDimensions)] = value;

int to1d(int* position, int* dimensionSizes, int numDimensions){
    int multiplier = 1;
    int position1d = 0;
    for (int i = 0; i < numDimensions; ++i){
        position1d = position1d + position[i] * multiplier;
        multiplier = multiplier * dimensionSizes[i];
    }
    return position1d;
}

【讨论】:

  • 抱歉,OP 说他们想要 C,因此我删除了 C++ 标签
  • 顺便说一句,C 没有引用 afaik 并且在 C++ 中 malloc 应该与 free 匹配,而不是 delete(或者更确切地说是 newdelete 或更好的是不匹配 new没有delete)
  • 一维数组是个好主意,但是int access(int x, int y, int z) 说这仍然需要在编译时知道。也许是一个可变函数?但同样适用。 @EricPostpischil 建议的索引数组是有道理的。
【解决方案2】:

使用指向指针/双指针的指针 (**)。对于 n 维数组,您在循环中重复动态分配过程 (malloc) n 次,并使用指向新分配数组的指针来引用每个数组。唯一的问题是最后一个数组不使用双指针,因此您的运行时代码必须知道何时在最后一维使用值而不是双指针。使用它,您仍然可以通过M[1][2][3][1] = 5; 等传统语法进行设置/获取(请注意,0 是第一个元素!)。

还要确保初始化您的值。

有关双数组指针的一个很好的例子和论文,请查看 Kerningham/Richie 的“The C Progamming Language”,它可以在线获得。

注意:还有其他优雅但不那么优雅的解决方案。例如,使用宏/元编程在编译时编写分配代码并传递define 选项(-DDIMS=4)或表示像树这样的数组的可嵌套数据结构(查看经典数据结构文献以了解多维数组。)

【讨论】:

  • (a) C 有可变长度数组,它允许创建大小在运行时给定的数组。 (b) 这个问题似乎要求一个维数可变的数组,而不是维数可变的数组。
  • @Eric:感谢您的 cmets。我确实不在OP的问题上。还删除了代码,因为恕我直言,OP 应该自行执行此操作,并给出提示。
【解决方案3】:

您可以在运行时使用 VLA 设置数组的大小。可变长度 数组是 C99 的一部分。所以这只适用于 C99 或更高版本。虽然 C11 有 VLA 作为选项,但所有主要编译器都支持它。

假设您希望用户从终端输入二维数组的大小。

#include <stdio.h>

int main(void)
{
   unsigned int row1, col1;

   printf("%s", "Enter number of rows and columns in a 2-D array: ");
   int row1, col1; // number of rows and columns in a 2-D array
   scanf("%u %u", &row1, &col1);

   int array2D[row1][col1]; // declare 2-D variable-length array

}

array2d 是在运行时声明的二维数组。然后只需在下面编写代码即可使用它。

在 C 的早期版本中,sizeof 始终是编译时操作,但当应用于 VLA 时,sizeof 在运行时操作。将打印 VLA 中的字节数:

【讨论】:

  • 除此之外,您可以使用动态分配以避免潜在的堆栈大小问题,int (*x)[col1] = malloc(row1 * sizeof *x);。当然,在继续声明数组之前验证 scanf 成功并且值大于零是明智的。
  • @MM 我把它改成了一个无符号整数,所以没有负数。但它仍然不是那么安全,它很容易溢出堆栈,如果有人制作 100000 x 100000 它将使用 10000000000 x 4 字节.哪个应该溢出堆栈。此答案旨在表明 V:LA 编码不安全。
猜你喜欢
  • 1970-01-01
  • 2023-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-16
  • 1970-01-01
  • 2022-01-01
  • 1970-01-01
相关资源
最近更新 更多