c-来自外部函数分配的动态矩阵2D数组malloc()



我正试图从非主函数加载文件,并将指针到指针(2D矩阵(作为ANSI C.中的参数

使用l值函数的方法是正确的:

float **loadArray(int *rows, int *columns) {
float **array;
FILE *instream; // input file pointer
char infile[21] = {}; //20 chars max filename length
int i = 0, j = 0; //iterators
printf("filename to load data from: ");
scanf(" %20s", infile);
if (!(instream = fopen(infile, "r"))) {
perror("fopen() error");
exit(-1);
}
fread(rows, sizeof(int), 1, instream);
fread(columns, sizeof(int), 1, instream);
fprintf(stdout, "narray(%d,%d):", *rows, *columns); //OK
// allocation of vertical array containing rows pointers.
if (!(array = (float**)malloc((*rows) * sizeof(float*)))) {
printf("vertical malloc() error");
exit(-1);
}
for (i = 0; i < (*rows); i++) 
// for every row allocate columns space
if (!(array[i] = (float*)malloc((*columns) * sizeof(float)))) {
printf("horizontal malloc() error");
exit(-1);
}
for (i = 0; i < (*rows); i++)
for (j = 0; j < (*columns); j++)
fread((&array[i][j]), sizeof(float), 1, instream);
fclose(instream);
return array;
}
int main() {
int i = 0;
int rows = 0, columns = 0;
float **myarray;
myarray = loadArray(&rows, &columns);
...
for (i = 0; i < rows; i++)
free(myarray[i]);
free(myarray);
}

但我试图在读取文件时保持一致,rowscolumns作为地址以相同的方式传递数组:

int loadArray2(float ***array, int *rows, int *columns) {
FILE *instream; // input file pointer
char infile[21] = {}; //20 chars max filename length
int i = 0, j = 0; //iterators
printf("filename to load data from: ");
scanf(" %20s", infile);
if (!(instream = fopen(infile, "r"))) {
perror("fopen() error");
exit(-1);
}
fread(rows, sizeof(int), 1, instream);
fread(columns, sizeof(int), 1, instream);
fprintf(stdout,"narray(%d,%d):", *rows, *columns); //OK
// allocation of vertical array containing rows pointers.
if (!(*array = (float**)malloc((*rows) * sizeof(float*)))) {
printf("vertical malloc() error");
exit(-1);
}
for (i = 0; i < (*rows); i++) 
// for every row allocate columns space
if (!(*array[i] = (float*)malloc((*columns) * sizeof(float)))) {
printf("horizontal malloc() error");
exit(-1);
}
for (i = 0; i < (*rows); i++)
for (j = 0; j < (*columns); j++)
fread((array[i][j]), sizeof(float), 1, instream);
fclose(instream);
return 0;
}
int main() {
int rows = 0, columns = 0;
float **myarray;
loadArray2(&myarray, &rows, &columns);
...
for (i = 0; i < rows; i++)
free(myarray[i]);
free(myarray);
}

但这种方法失败了。我想我在CCD_ 3调用"无错误"或"警告"时出错了,或者我的逻辑不好,我承认我迷路了。。。

谢谢你的建议。

在失败函数中,一个主要问题是array是指向float **的指针,您需要取消引用该指针才能获得原始float **变量。就像处理rowscolumns参数一样。

因此,您需要执行(*array)[i][j],而不是执行例如array[i][j]

loadArray2中使用三指针时,请记住后缀运算符比前缀运算符绑定得更紧密。因此,在存储指向已分配的float数组的指针时,应该写入(*array)[i],在读取浮点值时写入&(*array)[i][j]

请注意,您的代码中还有其他问题:

  • char infile[21] = {};在C中不是一个有效的语法(它在C++中,您的编译器可能支持它作为扩展,或者可能是因为您将此代码编译为C++(。改为写入char infile[21] = "";
  • 由于您正在从文件中读取二进制数据,因此应该以二进制模式打开它:fopen(infile, "rb")。它在linux和Mac/OS上可能没有什么不同,但在遗留系统上肯定是一个错误
  • 您应该检查读取错误
  • 您可以在一次调用中读取矩阵行(在第一个选项的代码下方(:

    for (i = 0; i < (*rows); i++) {
    if (fread(array[i], sizeof(float), *cols, instream) != *cols) {
    // handle the read error
    }
    }
    

是否使用第一种或第二种方法存在争议:

  • 在第一种情况下,NULL指针很容易返回错误,因此通过引用传递间接2D数组指针似乎没有必要。在C中返回此指针是一种更惯用的方法。如果需要有关错误的更多信息,可以将指向错误代码的指针作为额外的参数
  • 在第二种情况下,可以直接返回错误代码以进行更精确的诊断,但正如您刚刚经历的那样,三元指针很容易出错。这种类型是不鼓励的。不要成为树星程序员:(

另一种方法是将指针以及行和列属性封装在一个结构中,并将指针传递到目标结构。

这是一个使用这种方法的修改版本:

#include <stdio.h>
#include <stdlib.h>
struct matrix {
int cols, rows;
float **data;
};
void matrix_reset(struct matrix *mat) {
int i;
if (mat->data) {
for (i = 0; i < mat->rows; i++)
free(mat->data[i]);
free(mat->data);
mat->data = NULL;
}
mat->rows = 0;
mat->cols = 0;
}
int matrix_load(struct matrix *mat) {
FILE *instream; // input file pointer
char infile[257] = ""; //256 chars max filename length
printf("filename to load data from: ");
if (scanf(" %256s", infile) != 1) {
perror("invalid input");
return -1;
}
if (!(instream = fopen(infile, "rb"))) {
perror("fopen() error");
return -2;
}
if (fread(&mat->rows, sizeof(int), 1, instream) != 1
||  fread(&mat->cols, sizeof(int), 1, instream) != 1) {
perror("fread() error");
fclose(instream);
return -3;
}
fprintf(stdout, "narray(%d,%d):", mat->rows, mat->cols);
// allocation of vertical array containing rows pointers.
if (!(mat->data = calloc(mat->rows, sizeof(*mat->data)))) {
printf("vertical malloc() error");
fclose(instream);
return -4;
}
for (int i = 0; i < mat->rows; i++) {
// for every row allocate columns space
if (!(mat->data[i] = calloc(mat->cols, sizeof(*mat->data[i])))) {
printf("horizontal malloc() error");
matrix_reset(mat);
fclose(instream);
return -5;
}
}
for (i = 0; i < mat->rows; i++)
if (fread(&mat->data[i], sizeof(*mat->data[i]), mat->cols, instream) != mat->cols) {
printf("horizontal malloc() error");
matrix_reset(mat);
fclose(instream);
return -6;
}
}
fclose(instream);
return 0;
}
int main() {
struct matrix m = { 0, 0, NULL};
if (!matrix_load(&m)) {
...
}
matrix_reset(&m);
return 0;
}

最新更新