从文本文件读取后矩阵元素未正确存储

时间:2018-06-12 08:01:03

标签: c arrays matrix binary indices

我目前正在尝试从c中的文本文件中读取矩阵,我试图将矩阵的元素存储在c中的2D数组中。

例如在名为" 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   

我真的很感激知道为什么元素没有在Matrix中正确存储,我在进行矩阵乘法时证实了这一点。

2 个答案:

答案 0 :(得分:1)

看来你的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,这是不必要的。请参阅: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)

始终确认已释放已分配的所有内存并且没有内存错误。

仔细看看,如果您有其他问题,请告诉我。

答案 1 :(得分:0)

看起来存储矩阵没有问题。歪斜的显示似乎是由于屏幕上的空间有限造成的。只需通过更改行

将标签替换为两个空格即可
 printf("%d\t", Matrix[i][j]);

 printf("%d  ", Matrix[i][j]);

这应该有效。