【问题标题】:Elements of matrix not being stored correctly after reading from a text file从文本文件读取后矩阵元素未正确存储
【发布时间】:2018-11-21 13:14:32
【问题描述】:

我目前正在尝试从 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   

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

【问题讨论】:

    标签: c arrays matrix binary indices


    【解决方案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的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)
    

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

    检查一下,如果您还有其他问题,请告诉我。

    【讨论】:

    • @David C. Rankin 谢谢你的回答!我将保持自己的方法,只是更改制表符分隔符。而且我确实添加了一个免费的,我只是没有在我发布的代码中显示它。就我而言,它不像你的那样免费。 :)
    • 如果您保留自己的unsigned **,那么您必须先释放每一行matrix[i],然后再释放matrix。这样做并没有错——你只需要做更多的计算来确保你释放了所有的内存。请记住mallocfree 总是成对出现。因此,请跟踪您所有的mallocs——您将需要多次致电free。祝你的编码好运:)
    【解决方案2】:

    看起来像这样存储矩阵没有问题。歪斜的显示似乎是由屏幕上的空间有限造成的。只需通过更改行将制表符替换为两个空格

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

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

    应该可以的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-15
      • 1970-01-01
      • 2018-08-12
      • 2015-06-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多