【问题标题】:Allocating 2D array of dimensions read from file分配从文件读取的二维维度数组
【发布时间】:2018-07-28 08:01:24
【问题描述】:

我想从文本文件中读取两个数字n,m,然后分配一个包含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;
}

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

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

【问题讨论】:

  • 这是什么:&&array
  • @machine_1想要传递一个指向数组的指针。
  • @Itay4 有什么问题?
  • 您不能为func 中的参数int **array 分配,除非返回新分配的指针以在调用者中分配。 func 接收指针的副本(其地址与main() 中的array 完全不同)。为了在不提供返回的情况下进行分配,那么您必须传递array地址(例如,参数必须是func (int ***array, *rows, *cols)并将其称为func (&array, &rows, &cols),您必须同时分配指针和存储对于 m 每个指针的整数。(注意:成为 C 中的 3 星程序员 并不是恭维)
  • @DataChanturia 问题是根据我从文本文件中读取的维度分配二维数组的最佳实践是什么。

标签: c multidimensional-array c89


【解决方案1】:

首先是这里最大的错误:

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

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

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

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


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


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

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

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

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


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

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

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

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


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

【讨论】:

  • 您可能会指出他声明了int rows, cols; 并传递了&amp;rows, &amp;colsfunc 正确地采用了int *rows, int *cols( 和int地址成为指针参数) -- 那么为什么他认为声明int **array 然后(尝试...)传递array地址 需要int ** 参数?额外的间接级别消失在哪里? (你也可以骂一下启用编译器警告;)
  • @DavidC.Rankin 你是对的,但是这段代码充满了错误,我决定最好只是回答直接的问题。将添加有关警告的提示,但希望它们也有助于查找/调试其他错误。
  • 对不起,忘了说我用的是ISO C90,所以我不能用VLA,而且我不知道二维的大小,我该怎么做你建议的?
  • @Itay4 两个选项:实际使用指针到指针类型(这在此答案中显示为第二种选择) - 或者,使用大小为 x*y 的平面数组并计算行- 在访问它时为自己建立索引(这会产生与真正的二维数组基本相同的编译代码,但需要更多的工作来编写)。
  • @Itay4 - 你可以声明int **array,然后为每个指针分配m ints 的指针和存储空间——但你必须弄清楚如何让指针指向您在func 中新分配的array 回到main()。您正确处理了rowscols - 您看到应该如何处理array 的绊脚石是什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-23
相关资源
最近更新 更多