我正试图从非主函数加载文件,并将指针到指针(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);
}
但我试图在读取文件时保持一致,rows
、columns
作为地址以相同的方式传递数组:
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 **
变量。就像处理rows
和columns
参数一样。
因此,您需要执行(*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;
}