首页 > 解决方案 > 分配从文件读取的二维维度数组

问题描述

我想n,m从文本文件中读取 2 个数字,然后分配一个包含n行和m列的二维数组。

另外,我想在我的main函数中初始化数组,以便稍后在其他函数中使用它,并在另一个函数中进行读取和分配,我将从main函数中调用它。

我知道如何处理读数,但我在数组分配上苦苦挣扎。

我在这里阅读了很多类似问题的答案,但它们并没有帮助我。

我编写了以下代码,但不确定如何继续使用它以获得所需的结果:

void func(int** array, int* rows, int* cols){
  int n, m;
  FILE *file;
  fp = fopen("test.txt", "r");
    if (file) {
    /* reading numbers n and m */
    *rows = n;
    *cols = m;
    **array = (int*)malloc(n * m * sizeof(int));
    fclose(file);
  }
}

int main() {      
  int rows, cols;
  int** array;
  func(&array, &rows, &cols);
  return 0;
}

我想也许我应该先分配一个 2D 数组,calloc然后realloc在阅读后使用n,m,但不确定这是否是最佳做法。

根据我从文本文件中读取的维度分配二维数组的最佳实践是什么?

标签: cmultidimensional-arrayc89

解决方案


首先是这里最大的错误:

  • 您的函数在函数签名中没有任何类型- 这应该被编译器拒绝
  • 二维数组指针数组不同
  • 应该是什么&&意思?&是某物的地址,它的结果不能有地址,因为它没有存储在任何地方,所以这没有意义

如果您想动态分配一个真正的二维数组,您需要固定第二维或使用带有变量的 VLA(在 C11 中是可选的,但假设支持非常安全)。像这样的东西:

// dimensions in `x` and `y`, should be of type `size_t`
int (*arr)[x] = malloc(y * sizeof *arr);

在任何情况下,第二维都是类型的一部分,因此您的结构将不起作用——调用代码必须知道第二维才能传递有效指针。


提示:这第一部分不再适用于这个问题,OP忘了提到他只对C90感兴趣。我添加了适当的标签,但将答案的上半部分留作参考。以下内容也适用于 C90:


int **在代码中编写,这将是指向指针的指针。您可以通过使用指向指针的指针来创建可以像二维数组一样使用的东西但是,您不能将其分配为单个块。

外部指针将指向一个指针数组(例如,“行指针”),因此对于这些指针中的每一个,您必须分配一个实际值数组。这可能如下所示:

// dimensions again `x` and `y`
int **arr = malloc(y * sizeof *arr);
for (size_t i = 0; i < y; ++i)
{
    arr[i] = malloc(x * sizeof **arr);
}

请注意,这两个片段都是最小的示例。对于实际代码,您必须检查malloc()每次的返回值。它可以在失败时返回一个空指针。


如果您想在没有 VLA 的情况下拥有一个连续的内存块,最后可以选择只使用常规数组并自己计算索引,例如:

int *arr = malloc(x * y * sizeof *arr);

// access arr[8][15] when x is the second dimension:
arr[x*8 + 15] = 24;

这将生成(大致)与真实二维数组相同的可执行代码,但在您的源代码中当然看起来不太好。


请注意,这只不过是对您的直接问题的直接回答。您的代码包含更多错误。您应该真正启用一组合理的编译器警告(例如,使用gccor clang,使用-Wall -Wextra -pedantic -std=c11标志),然后修复您在继续项目时收到的每一个警告。


推荐阅读