您的tab 分隔符似乎导致您的输出在终端边缘换行,将每行中的最终值放在自己的一行中。除了您未能free 您使用的内存之外,您的代码正在运行。
这并不意味着你没有问题,或者不能以更方便的方式做一些事情——这会让你更容易释放记忆——只需要一次调用free。
不是声明unsigned **Matrix(指向类型指针的指针),而是将矩阵声明为指向无符号[cols_Matrix]数组的指针。 (本质上是一个指向 COLS unsigned 值数组的指针。那么您只需要分配 3 行来为您的矩阵分配所有存储空间。
(我避免打字,所以下面示例中的变量更短......)
例如,您可以将matrix 声明为
#define ROWS 3
#define COLS 16
...
unsigned (*matrix)[COLS] = NULL, /* pointer to array of COLS elem */
row = 0, /* row counter */
col = 0; /* column counter */
现在只需要一次分配:
matrix = malloc (ROWS * sizeof *matrix); /* allocate matrix */
if (!matrix) { /* validate allocation */
perror ("malloc-matrix");
return 1;
}
(malloc的return不用投,没必要。见:Do I cast the result of malloc?)
其余部分与您所做的类似。从带有fscanf 和%u(或任何数字转换说明符)的文件中读取格式化整数值没有任何问题,因为数字转换说明符将占用所有前导空格(包括换行符)。但是,您确实需要在读取期间明确检查行/列以保护您的内存边界并防止在分配的块之外写入,例如
/* read while row < ROWS & good value read */
while (row < ROWS && fscanf (fp, "%u", &matrix[row][col]) == 1) {
if (++col == COLS) { /* increment col, test against COLS */
row++; /* on match - increment row */
col = 0; /* reset col */
}
}
现在您必须验证是否正确读取了所有数据。检查row == ROWS 的最终值提供确认,例如
if (row != ROWS) { /* validate all data read */
fprintf (stderr, "error: failed to read all %dx%d matrix.\n",
ROWS, COLS);
return 1;
}
然后输出数据进行确认并释放你分配的内存是一件简单的事情,例如
for (unsigned i = 0; i < ROWS; i++) { /* output matrix */
for (unsigned j = 0; j < COLS; j++)
printf ("%4u", matrix[i][j]);
putchar ('\n');
}
free (matrix); /* don't forget to free mem (single free!) */
总而言之,您可以执行以下操作:
#include <stdio.h>
#include <stdlib.h>
#define ROWS 3
#define COLS 16
int main (int argc, char **argv) {
unsigned (*matrix)[COLS] = {NULL}, /* pointer to array of COLS elem */
row = 0, /* row counter */
col = 0; /* column counter */
/* read file provided as 1st argument (default stdin if no argument) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
matrix = malloc (ROWS * sizeof *matrix); /* allocate matrix */
if (!matrix) { /* validate allocation */
perror ("malloc-matrix");
return 1;
}
/* read while row < ROWS & good value read */
while (row < ROWS && fscanf (fp, "%u", &matrix[row][col]) == 1) {
if (++col == COLS) { /* increment col, test against COLS */
row++; /* on match - increment row */
col = 0; /* reset col */
}
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
if (row != ROWS) { /* validate all data read */
fprintf (stderr, "error: failed to read all %dx%d matrix.\n",
ROWS, COLS);
return 1;
}
for (unsigned i = 0; i < ROWS; i++) { /* output matrix */
for (unsigned j = 0; j < COLS; j++)
printf ("%4u", matrix[i][j]);
putchar ('\n');
}
free (matrix); /* don't forget to free mem (single free!) */
return 0;
}
输入文件示例
$ cat dat/3x16mat.txt
0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 0
0 0 0 1 0 0 1 0 1 0 0 0 1 0 0 0
0 1 0 0 1 0 1 0 0 1 0 0 0 0 0 0
使用/输出示例
$ ./bin/matrix_3x16 dat/3x16mat.txt
0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 0
0 0 0 1 0 0 1 0 1 0 0 0 1 0 0 0
0 1 0 0 1 0 1 0 0 1 0 0 0 0 0 0
内存使用/错误检查
在您编写的任何动态分配内存的代码中,对于分配的任何内存块,您都有 2 个职责:(1)始终保留指向起始地址的指针内存块,因此 (2) 当不再需要它时可以释放。
您必须使用内存错误检查程序来确保您不会尝试访问内存或写入超出/超出分配块的边界,尝试读取或基于未初始化的值进行条件跳转,最后,以确认您释放了已分配的所有内存。
对于 Linux,valgrind 是正常的选择。每个平台都有类似的内存检查器。它们都易于使用,只需通过它运行您的程序即可。
$ valgrind ./bin/matrix_3x16 <dat/3x16mat.txt
==24839== Memcheck, a memory error detector
==24839== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==24839== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==24839== Command: ./bin/matrix_3x16
==24839==
0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 0
0 0 0 1 0 0 1 0 1 0 0 0 1 0 0 0
0 1 0 0 1 0 1 0 0 1 0 0 0 0 0 0
==24839==
==24839== HEAP SUMMARY:
==24839== in use at exit: 0 bytes in 0 blocks
==24839== total heap usage: 1 allocs, 1 frees, 192 bytes allocated
==24839==
==24839== All heap blocks were freed -- no leaks are possible
==24839==
==24839== For counts of detected and suppressed errors, rerun with: -v
==24839== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始终确认您已释放已分配的所有内存并且没有内存错误。
检查一下,如果您还有其他问题,请告诉我。