Вопрос по fread, pointers, arrays, c – Чтение 2d массива из двоичного файла и возврат указателя этого массива (в C)

3

Я пытаюсь написать функцию, которая возвращает указатель двумерного массива, считанного из двоичного файла. Хотя я компилирую без ошибок, всегда возникает ошибка сегментации, когда я пытаюсь распечатать один из элементов массива. Вот мой код:

double ** readArray(int rows, int cols)
{
   int i;
   double **myArray=malloc(rows*sizeof(double*));
   if (myArray){ 
      for (i=0; i < rows; i++)
      {
        myArray[i]=malloc(cols*sizeof(double));
      }
   }        

   FILE *data;
   data=fopen("matrix.bin", "rb");
   fread(myArray,sizeof(double),rows*cols,data);

   return myArray; 
}

int main ()
{
  int cols = 7;
  int rows = 15;
  double **myArray=readArray(rows, cols);
  printf("%f\n", myArray[1][0]);
  return 0; 
}
Ты забылfree() что тыmalloc() «изд Michi
Посмотрите наC FAQ раздел 6.16 и использовать второй способ для выделения непрерывной памяти. Если вы можете убедиться, что память непрерывна, вы можете прочитать весь файл однимfread() как твой код делает. Но также рассмотреть возможность использованияmmap() Øystein Schønning-Johansen
myArray не является непрерывной областью памяти, каждое выделение, которое вы делаете, может возвращать указатель практически на любое место в свободном пространстве. Смотрите, например,этот мой старый ответ за разницу между массивом массивов и указателем на указатель «матрица». Some programmer dude

Ваш Ответ

2   ответа
2

что в вашем коде нет 2D-массива. Таблица поиска указателя к указателю не является двумерным массивом. Это [ряды] количество сегментов, разбросанных по всей куче, в случайных местах. Поэтому это также излишне медленно.

Кроме того, вы должны разделять память и алгоритмы.

Сделайте что-то вроде этого:

#include <stdio.h>
#include <stdlib.h>

void* allocArray (int rows, int cols)
{
  return malloc( sizeof(double[rows][cols]) ); // allocate 1 2D-array
}

void readArray (int rows, int cols, double array[rows][cols])
{
   FILE *data;
   data=fopen("matrix.bin", "rb");
   fread(array, sizeof(double[rows][cols]), 1, data); // read 1 2D-array
}

int main ()
{
  int cols = 7;
  int rows = 15;
  double (*myArray)[cols] = allocArray(rows, cols);

  readArray(rows, cols, myArray);

  printf("%f\n", myArray[1][0]);

  free(myArray); // free 1 2D-array
  return 0; 
}

Причина своеобразной декларацииdouble (*myArray)[cols] вместо более логичногоdouble (*myArray)[rows][cols], что мы хотим избежать неудобного синтаксиса разыменования указателя массива.(*myArray)[1][0] не легко читать. Поэтому вместо того, чтобы объявлять указатель массива на двумерный массив, объявите указатель массива на одномерный массив, а затем используйте индексацию указателя для этого указателя массива. Для любого указателя,any_pointer[n] указывает на пункт номер n. Указатели на массив не имеют значения, поэтому вы получаете 1D номер массива n.

Большое спасибо, ваше объяснение было просто великолепно! LAM
1

Вашfread() call перезаписывает все те указатели, которые вы мучительно настроили.

Вам нужно читать по одной строке за раз и использовать указатель установки для сохранения в:

for(size_t i = 0; i < rows; ++i)
  fread(myArray[i], cols * sizeof *myArray[i], data);

Кроме того, при выполнении операций ввода-вывода и выделения памяти вы должны, конечно, также проверять возвращаемые значения.

Похожие вопросы