В вашем коде по-прежнему отсутствует информация, но ваша функция initMatrix()
имеет большое количество мелких проблем. Вы используете cols
, где rows
следует использовать для выделения указателей. Вы не можете проверить какое-либо распределение или пользовательский ввод. Это рецепт неопределенного поведения. Кроме того, вы не предоставляете код для определения того, что такое numberOfMatrices
или как объявляется orderedMatricesInfo
. С учетом этих предостережений вы можете исправить немедленные ошибки в initMatrix()
следующим образом:
int **initMatrix(int rows, int cols)
{
int matrix[rows][cols];
int **matrixPointer;
/* allocate rows number of pointers */
matrixPointer = malloc (sizeof *matrixPointer * rows);
if (!matrixPointer) { /* validate EVERY allocation */
perror ("malloc-*matrixPointer");
return NULL;
}
/* you must allocate rows number of cols * sizeof(int) blocks
* assigning the starting address to each of your allocated pointers.
* (always use the dereferenced pointer to set type-size)
*/
for (int i = 0; i < rows; ++i)
{ /* use calloc on rows to initialize all bytes zero */
matrixPointer[i] = calloc (sizeof *matrixPointer[i], cols);
if (!matrixPointer[i]) { /* validate EVERY allocation */
perror ("calloc-matrixPointer[i]");
while (i--) /* on error, free prior memory */
free (matrixPointer[i]);
free (matrixPointer);
return NULL;
}
}
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < cols; ++j)
{
while (1) { /* loop continually until valid integer provided */
printf ("\nPlease enter element for [%d][%d]: \n", i, j);
/* validate EVERY user-input */
if (scanf("%d", &matrixPointer[i][j]) == 1)
break;
fputs (" error: invalid integer input.\n", stderr);
}
}
}
/* your code does not provide information on the following */
++numberOfMatrices;
orderedMatricesInfo[numberOfMatrices-1][0][0] = rows;
orderedMatricesInfo[numberOfMatrices-1][0][1] = cols;
allocateMatrix(rows, cols); /* why allocate -- that's what you just did?? */
saveMatrix(matrixPointer, rows, cols);
return matrixPointer;
}
(не проверено, так как ваш код неполный. Код прокомментирован, объясняя дополнения)
Обратите внимание, ваш allocateMatrix(int rows, int cols)
просто теряет память. Возврат не назначается какому-либо указателю, поэтому вы потеряли начальный адрес выделенного блока и не можете его освободить.
В любом написанном вами коде, который динамически выделяет память, у вас есть 2 обязанности в отношении любого выделенного блока памяти: (1) всегда сохранять указатель на начальный адрес для блока памяти. память, поэтому (2) ее можно освободить, когда она больше не нужна.
Дайте мне знать, если у вас есть вопросы, и предоставьте минимальный, полный и проверяемый пример (MCVE) для получения дополнительной помощи.
Дополнительная информация об ошибках
Остальная часть вашего кода имеет ту же проблему rows
и cols
, когда вы пытаетесь выделить cols
количество указателей (вместо rows
количества указателей). Однако проблема, приведшая к вашему SEGFAULT, была связана с numberOfMatrices
и файлом, который вы пытаетесь открыть, не по одному. Это было решено путем обеспечения того, чтобы ваши циклы последовательно индексировали 0 < numberOfMatrices
и размещали номер файла с помощью:
matrixPointer = readMatrix(matrixRows, matrixCols, matrix, matrixNum + 1);
Добавление 1
к matrixNum, переданному readMatrix
. Это простой способ сохранить прямую нумерацию. Ваш код записывает и читает файл правильно, но обратите внимание, что вы выполняете добавление к файлу, поэтому вам придется дополнительно работать, чтобы получить доступ к каждой из матриц, хранящихся в вашем выходном файле (вы должны указать количество rows
и cols
в файл перед записью каждой матрицы, поэтому вы можете прочитать файл обратно, прочитав 2 значения int
, чтобы определить размер следующей матрицы, которая остается вам.
Когда он находится, ваша функция отображения будет читать файл, предполагая, что первые целые числа в файле относятся к текущей матрице, что не так. Целочисленные значения, прочитанные для отображения, являются элементами первой матрицы, записанной в файл, которые не будут совпадать с текущими значениями матрицы, если только вы не записываете и не читаете первый набор значений. В противном случае текущие значения матриц содержатся в файле после байтов всех предыдущих матриц, которые были записаны в файл. Более полезным форматом файла будет:
no_matricies rows cols ...... rows cols ......
Где первое записанное целочисленное значение содержит количество матриц, записанных в файл, за которым следуют row
, col
и .... data
для каждой матрицы, что позволит получить доступ ко всем матрицам и позволит обновить первое целочисленное значение в файле без повторного запись всего файла. (это тоже остается на ваше усмотрение)
Ваш очищенный код выглядит следующим образом. Примечание. Я изменил использование вами sprintf
и устранил ненужную конкатенацию. Я также упростил копирование из matrix
в matrixPointer
, используя memcpy()
:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
int numberOfMatrices = 0;
int orderedMatricesInfo[100][1][2];
int matrixRows = 0;
int matrixCols = 0;
int** initMatrix(int rows, int cols);
void saveMatrix(int** matrix, int rows, int cols);
void* allocateMatrix(int rows, int cols);
int** readMatrix(int rows, int cols, int matrix[matrixRows][matrixCols], int matrixNum);
void displayMatrices();
void displayMatrix(int rows, int cols, int** matrix);
int main()
{
int n, m;
int** matrixPointer;
printf("Please enter the number of rows in your matrix: \n");
if (scanf("%d", &n) != 1) {
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
printf("Please enter the number of columns in your matrix: \n");
if (scanf("%d", &m) != 1) {
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
matrixPointer = initMatrix(n, m);
// printf("%d\n", matrixPointer[0][0]);
displayMatrices();
printf("SUCCESS");
}
int **initMatrix(int rows, int cols)
{
int **matrixPointer;
/* allocate rows number of pointers */
matrixPointer = malloc (sizeof *matrixPointer * rows);
if (!matrixPointer) { /* validate EVERY allocation */
perror ("malloc-*matrixPointer");
return NULL;
}
/* you must allocate rows number of cols * sizeof(int) blocks
* assigning the starting address to each of your allocated pointers.
* (always use the dereferenced pointer to set type-size)
*/
for (int i = 0; i < rows; ++i)
{ /* use calloc on rows to initialize all bytes zero */
matrixPointer[i] = calloc (sizeof *matrixPointer[i], cols);
if (!matrixPointer[i]) { /* validate EVERY allocation */
perror ("calloc-matrixPointer[i]");
while (i--) /* on error, free prior memory */
free (matrixPointer[i]);
free (matrixPointer);
return NULL;
}
}
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < cols; ++j)
{
while (1) { /* loop continually until valid integer provided */
printf ("\nPlease enter element for [%d][%d]: \n", i, j);
/* validate EVERY user-input */
if (scanf("%d", &matrixPointer[i][j]) == 1)
break;
fputs (" error: invalid integer input.\n", stderr);
}
}
}
/* move numberOfMatrices++ below the assignment */
orderedMatricesInfo[numberOfMatrices][0][0] = rows;
orderedMatricesInfo[numberOfMatrices][0][1] = cols;
numberOfMatrices++;
// allocateMatrix(rows, cols); /* why allocate -- that's what you just did?? */
saveMatrix(matrixPointer, rows, cols);
return matrixPointer;
}
void saveMatrix(int** matrix, int rows, int cols)
{
char fullFileName[256];
sprintf (fullFileName, "matrix-%02d.txt", numberOfMatrices);
FILE *file = fopen(fullFileName, "ab");
if (!file) { /* validate file open for writing */
perror ("fopen-file");
return;
}
for(int i=0; i<rows; ++i)
{
fwrite(matrix[i], sizeof *matrix[i], cols, file);
}
if (fclose(file) == EOF) /* always validate close after write */
perror ("fclose-file");
}
void *allocateMatrix(int rows, int cols)
{
return malloc(sizeof(int[rows][cols]));
}
int **readMatrix(int rows, int cols, int matrix[matrixRows][matrixCols], int matrixNum)
{
int **matrixPointer;
matrixPointer = malloc(sizeof *matrixPointer * rows); /* rows not cols!! */
if (!matrixPointer) { /* validate EVERY allocation */
perror ("malloc-*matrixPointer");
return NULL;
}
for (int i =0; i < rows; ++i) /* rows not cols!! */
{
matrixPointer[i] = calloc (sizeof *matrixPointer[i], cols);
if (!matrixPointer[i]) { /* validate EVERY allocation */
perror ("calloc-matrixPointer[i]");
while (i--) /* on error, free prior memory */
free (matrixPointer[i]);
free (matrixPointer);
return NULL;
}
}
char fullFileName[256];
sprintf (fullFileName, "matrix-%02d.txt", matrixNum);
FILE *file = fopen(fullFileName, "rb");
if (!file) { /* validate file open for reading */
perror ("fopen-file");
for (int i = 0; i < rows; i++) /* on error free memory */
free (matrixPointer[i]);
free (matrixPointer);
return NULL;
}
/* validate EVERY input */
if (fread (matrix, sizeof(int[rows][cols]), 1, file) < 1) { // read 1 2D-array
for (int i = 0; i < rows; i++) /* on error free memory */
free (matrixPointer[i]);
free (matrixPointer);
return NULL;
}
for (int i = 0; i < rows; ++i)
{
memcpy (matrixPointer[i], matrix[i], sizeof *matrixPointer[i] * cols);
/*
for (int j = 0; j < cols; ++j)
{
matrixPointer[i][j] = matrix[i][j];
printf("%d", matrixPointer[i][j]);
}
*/
}
// allocateMatrix(rows, cols); /* not needed */
return matrixPointer;
}
void displayMatrices()
{
for (int matrixNum = 0; matrixNum < numberOfMatrices; matrixNum++)
{
char fullFileName[256];
sprintf (fullFileName, "matrix-%02d.txt", numberOfMatrices);
matrixRows = orderedMatricesInfo[matrixNum][0][0];
matrixCols = orderedMatricesInfo[matrixNum][0][1];
int matrix[matrixRows][matrixCols];
int **matrixPointer;
matrixPointer = readMatrix(matrixRows, matrixCols, matrix, matrixNum + 1);
displayMatrix(matrixRows, matrixCols, matrixPointer);
}
}
void displayMatrix(int rows, int cols, int** matrix)
{
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < cols; ++j)
{
printf (" %2d", matrix[i][j]);
}
putchar ('\n');
}
putchar ('\n');
}
(примечание: в приведенном выше коде оставлен ряд дополнительных комментариев, а не подробное описание каждого предлагаемого изменения в форме абзаца)
Пример использования/вывода
$ ./bin/write_matrix
Please enter the number of rows in your matrix:
2
Please enter the number of columns in your matrix:
2
Please enter element for [0][0]:
1
Please enter element for [0][1]:
2
Please enter element for [1][0]:
3
Please enter element for [1][1]:
4
1 2
3 4
SUCCESS
Просмотрите все и дайте мне знать, если у вас есть дополнительные вопросы.
person
David C. Rankin
schedule
11.11.2020
matrixPointer = malloc(sizeof(int*)*cols);
Вам нужноrows
, а неcols
количество указателей. Вам также нужноint
неint*
вmatrixPointer[i] = malloc(sizeof(int*)*cols);
(дляcols
количестваint
неcols
количества указателей) - person David C. Rankin   schedule 11.11.2020orderedMatricesInfo[numberOfMatrices-1][0][0] = rows;
выглядит довольно подозрительно. Предоставьте минимальный, полный и проверяемый пример (MCVE). (что-то, что я могу скопировать и скомпилировать без создания прототипов функций и добавления заголовков и т. д.) - person David C. Rankin   schedule 11.11.2020rows
, вы должны выполнить циклfor (int i =0; i < rows; ++i)
- person David C. Rankin   schedule 11.11.2020