Элементы матрицы не сохраняются правильно после чтения из текстового файла - PullRequest
0 голосов
/ 12 июня 2018

В настоящее время я пытаюсь прочитать матрицу из текстового файла в 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   

Я был бы очень признателен, если бы знал, почему элементы не сохраняются в матрице правильно, и я подтвердил это, когда сделал умножение матриц.

Ответы [ 2 ]

0 голосов
/ 12 июня 2018

Похоже, что ваши 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, это не нужно. См .: Разве я разыгрываю результат 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 */
        }
    }

Теперь вы должны проверить, чтоальl Ваши данные были правильно прочитаны.Проверка окончательных значений 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!) */
* 1046.* В целом, вы можете сделать что-то вроде следующего:
#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)

Всегда подтверждайте, что вы освободили всю выделенную память и нет ошибок памяти.

Посмотрите вещии дайте мне знать, если у вас есть дополнительные вопросы.

0 голосов
/ 12 июня 2018

Похоже, что нет проблем с сохранением вашей матрицы как таковой.Похоже, что перекос дисплея вызван ограниченным пространством на вашем экране.Просто замените вкладку двумя пробелами, изменив строку

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

на

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

Это должно работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...