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