我正在尝试从c语言的文本文件中读取矩阵,并尝试将矩阵元素存储在c语言的二维数组中。
例如,在名为“Matrix.txt”的文本文件中,我当前有以下3X16矩阵:
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
我想在c中存储相同的精确矩阵。我实现的程序如下:
#include <stdio.h>
#include <stdlib.h>
#define rows_Matrix 3
#define cols_Matrix 16
int main()
{
unsigned **Matrix = (unsigned **)malloc(sizeof(unsigned *)*rows_Matrix); //Rows
for (int i = 0; i < rows_Matrix; i++) //Rows
{
Matrix[i] = (unsigned *)malloc(sizeof(unsigned) * cols_Matrix); //Columns
}
FILE *file;
file = fopen("Matrix.txt", "r");
for (int i = 0; i < rows_Matrix; i++)
{
for (int j = 0; j < cols_Matrix; j++)
{
//Read elements from a text file.
if (!fscanf(file, "%d", &Matrix[i][j]))
{
break;
}
}
}
fclose(file);
//Print Matrix.
for (int i = 0; i < rows_Matrix; i++)
{
for (int j = 0; j < cols_Matrix; j++)
{
printf("%d\t", Matrix[i][j]);
}
printf("\n");
}
return 0;
}
当存储和打印矩阵时,矩阵如下:
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
它应该以这种方式存储和打印:
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
我真的很高兴知道为什么元素没有被正确地存储在矩阵中,我在矩阵乘法时证实了这一点。
最佳答案
似乎是分隔符导致输出在终端边缘换行,将每行的最终值放在自己的行上。除了无法使用内存之外,您的代码还在工作。
这并不意味着你很清楚,或者不能用更方便的方式做一些事情——这会让你的内存释放变得更容易——只需要一次调用tab
。
不要声明free
(指向类型指针的指针),而是将matrix声明为指向无符号[cols_matrix]数组的指针。(本质上是指向free
unsigned **Matrix
值数组的指针。然后只需要分配3行就可以为矩阵分配所有存储。
(我避免键入,因此下面示例中的变量较短…)
例如,您可以将COLS
声明为
#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;
}
(不需要对
unsigned
的返回进行强制转换,这是不必要的。见:Do I cast the result of malloc?)剩下的和你做的相似。从
matrix
和malloc
文件(或任何数值转换说明符)中读取格式化整数值没有问题,因为数值转换说明符将使用所有前导空格(包括换行符)。但是,您确实需要在读取期间显式检查行/列,以保护内存边界并防止在分配的块之外写入,例如。 /* 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 */
}
}
现在必须验证所有数据都已正确读取检查
fscanf
的最终值可提供确认,例如。 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
内存使用/错误检查
在动态分配内存的任何代码中,对于任何分配的内存块,您都有两个职责:(1)始终保留指向内存块起始地址的指针,以便(2)在不再需要时可以释放它。
必须使用内存错误检查程序,以确保您不会尝试访问内存或写入超出或超出已分配块的界限,尝试读取未初始化值或将条件跳转基于未初始化值,最后确认您释放了已分配的所有内存。
对于Linux
%u
是正常的选择。每个平台都有类似的内存检查程序。它们都很容易使用,只要运行你的程序就可以了。$ 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)
始终确认已释放所有已分配的内存,并且没有内存错误。
再看一遍,如果你还有问题,请告诉我。
关于c - 从文本文件读取后矩阵元素未正确存储,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50812091/