问题:假设您正在尝试用 C 语言编写一个函数,该函数将使用文件中的值填充二维数组。该文件包含按行(记录)排列的值,其中每行包含多个字段。该函数应接收指向二维数组的指针和文件地址并填充数组。重要的是,该函数应该独立于每条记录有多少字段而工作。例如,在一个程序中,您可能会调用该函数从每个记录有四个字段的文件中读取值:
int array_of_values[MAX_NUMBER_OF_RECORDS][4];
fill_in_array(array_of_values, "spacetime.csv");
在另一个程序中,您可能希望在每条记录有 11 个字段时填写值:
int array_of_values[MAX_NUMBER_OF_RECORDS][11];
fill_in_array(array_of_values, "M-theory.csv");
不幸的是,如果你尝试这样做,你就会违反 C 处理多维数组的方式。多维数组在 C 中没有实现为指向数组的指针数组,而是作为一个长的一维数组。这意味着函数需要知道数组的宽度才能从中读取数据。
所以下面的函数定义会给你一个错误:
void fill_in_array(int array_of_values[MAX_NUMBER_OF_RECORDS][], char *path)
[请注意,以下内容很好:
void fill_in_array(int array_of_values[][MAX_NUMBER_OF_RECORDS], char *path)
因为编译器不需要知道第一维的索引,但假设这是不允许的(例如,如果函数需要处理单个记录,例如array_of_values[1]
)。]
这是我在我的程序中达到的点。有两种解决方案:
- 强制函数使用固定数量的字段。我显然不想这样做,但我可以,例如,声明一个常量
MAX_NUMBER_OF_FIELDS
并将未使用的字段留空。 - 使
fill_in_array
函数接受指针而不是数组,并动态分配包含字段的 Iliffe 向量。这是一个很有吸引力的想法(因为它会阻止我们必须声明最大数量的记录/字段,但这也意味着我们必须创建(并记住使用!)一个函数来释放字段数组。
我还有另一个想法。也就是将函数的声明修改为如下:
void fill_in_array(int **array_of_values, int number_of_fields, char *path)
(这里,number_of_fields
指的是每条记录的字段数,所以我们可以称它为fill_in_array(array_of_values, 4, "spacetime.csv");
.
请注意,参数array_of_values
不再是显式数组,而是指针。通常,如果你分配一个双指针指向一个二维数组,结果是没有意义的。我的想法是可以使用number_of_fields
参数,以便函数知道如何处理表达式,如array_of_values[i][j]
.
原则上这应该是相当容易的:事实上,如果a
是一个二维数组,那么a[i][j]
定义为
*(a + (i * n) + j)
其中n
是数组的长度,所以我们可以替换每次出现的array_of_values[i][j]
with*(array_of_values + (i * number_of_fields) + j)
和每次出现的array_of_values[i]
with array_of_values + (i * number_of_fields)
。但是,此代码将很难阅读。有没有办法告诉编译器数组的宽度是number_of_fields
这样我可以使用索引符号来访问数组的元素?