Передача указателя на массив структур в функцию для malloc - PullRequest
1 голос
/ 26 сентября 2019

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

Поэтому логично, что я пытаюсь сделать, это выделить массив указателей на структуры.То, что кажется неудачным, это попытка выделить память

мой код до сих пор:

typedef struct {
int tax, savings;
float salary;
} employee;

int readRecordFile(char* filename, Record*** array);

int main(void) {

employee** array;
int size;
char* file = "money.csv";
size = readRecordFile(file, &array);

FILE* fptr;
fptr = fopen(file, "r");


//Read the file into the the array 
for (int i = 0; i < size; i++) {
    fscanf(fptr, "%d,%d,%f", array[i]->tax, array[i]->savings, array[i]->salary);
}
fclose(fptr);


for (int i = 0; i < size; i++) {
    printf("%d, %d, %f\n", array[i]->tax, array[i]->savings, array[i]->salary);
}
return 0;
}

int readRecordFile(char* filename, employee*** array) {
//Function to open the file, malloc and initialize 2d arrays

//Open the file
FILE* fileptr;
fileptr = fopen(filename, "r");
if (fileptr == NULL) {
    printf("Failed to open file");
    exit(-1);
}

//Read first line of file (the size) and store to an int
int n;
fscanf(fileptr, "%d", &n);

//Initial malloc for the array of pointers
**array = malloc(n * sizeof(employee*)); //This is the line that throws the exception

//Malloc for each pointer in the array of pointers
for (int i = 0; i < n; i++) {
    *(array+i) = malloc(sizeof(employee));
}


//Close the file and return the size of the file
fclose(fileptr);

return n;
}

Я попытался создать отдельный указатель структуры внутри функции, а затем установить обычный указатель на нее

    //Initial malloc for the array of pointers
employee **tester = malloc(n * sizeof(employee*));

//Malloc for each pointer in the array of pointers
for (int i = 0; i < n; i++) {
    *(tester+i) = malloc(sizeof(employee));
}

array = tester;

Этот метод, по-видимому, устраняет проблемы, связанные с malloc, но при печати данных в main происходит сбой.

Ответы [ 2 ]

0 голосов
/ 26 сентября 2019

employee **array; НЕ является массивом, это одиночный указатель.( указатель на указатель на сотрудника ).

Какое значение size при вызове:

for (int i = 0; i < size; i++) 

size является неопределенным (его значениекакое бы значение мусора ни находилось в памяти при запуске программы).Вы вызываете неопределенное поведение , пытаясь получить доступ к неопределенному значению.size должен быть установлен перед использованием (одинаково для всех переменных)

В этой же точке array является неинициализированным указателем , пытающимся получить доступнеопределенный адрес так же плохо.(Помните, что указатель - это просто нормальная переменная, которая содержит адрес чего-то еще в качестве значения).Поскольку адрес, хранящийся в array, еще не был назначен, и для какой-либо структуры employee не было выделено ни одного хранилища, вы не можете выполнить:

fscanf(fptr, "%d,%d,%f", array[i]->tax, array[i]->savings, array[i]->salary);

Прежде чем использовать array, вы должны:

  1. выделяет некоторое количество указателей и назначает начало блока памяти, содержащего выделенные указатели, array, а затем
  2. выделяет память для каждой вашей структуры и назначает начальный адресдля каждого блока хранения, содержащего структуру одного из указателей array[i].

Например, чтобы первоначально объявить 64 указателя, вы можете сделать:

array = malloc (64 * sizeof *array);

( примечание: использование указателя с разыменованным указателем (sizeof *array) всегда приведет к правильному размеру шрифта, а не к попытке сопоставления с типом, например, sizeof (employee*))

ВСЕГДА проверяет каждое выделение, например

if (array == NULL) {            /* if the pointer returned by malloc is NULL */
    perror ("malloc-array");    /* issue diagnostic (perror is simple) */
    exit (EXIT_FAILURE);        /* handle error */
}

Теперь, как выделить для каждой структуры?(так же).Но подход, который намного легче читать, распределять и проверять, состоит в том, чтобы использовать временную структуру с автоматическим хранением и читать и заполнять временную структуру.Если чтение выполнено успешно, выделите место для вашей структуры, присвойте начальный адрес для этого блока памяти array[i], а затем присвойте содержимое временной структуры вашему новому блоку памяти.Например (после исправления size initialization):

for (int i = 0; i < size; i++) {
    employee tmp = { .tax = 0 };    /* declare temporary struct, initialized zero */
    /* read values into temporary struct / VALIDATE every input */
    if (fscanf (fptr, "%d,%d,%f", tmp.tax, tmp.savings, tmp.salary) == 3) {
        array[i] = malloc (sizeof *array[i]);   /* allocate for struct */
        if (!array[i]) {                        /* validate allocation */
            perror ("malloc-array[i]");
            exit (EXIT_FAILURE); 
        }
        array[i] = tmp;             /* assign temp struct to allocated block */
    }
}

Теперь, когда вы закончили с использованием вашего «массива», не забудьте освободить выделенную память.Например, предполагая, что вы правильно заполнили size, вы можете сделать следующее:

for (int i = 0; i < size; i++)
    free (array[i]);            /* free each allocated struct */
free (array);                   /* free pointers */

Возможно, в вашем опубликованном коде есть дополнительные ошибки (в некотором беспорядочном порядке), но это наиболеенемедленные ошибки, с которыми вы сталкиваетесь.Внесите изменения и протестируйте дальше.Убедитесь, что все переменные правильно инициализированы перед их использованием.Убедитесь, что вы выделили хранилище для каждого указателя, который будете использовать, а затем выделите для каждой структуры назначьте адрес для хранения структуры одному из ваших выделенных указателей.Если вы столкнулись с другим блокпостом, либо отредактируйте этот вопрос (или, желательно, задайте новый вопрос), указав конкретную проблему, на которой вы застряли.

0 голосов
/ 26 сентября 2019

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

Но вы читаете только одномерный массив структуры.(например, array[i]->tax)

Чтобы прочитать двумерный массив структуры, вам нужно 2 для циклов

for (int i = 0; i < size; i++) {
    for (int j=0; j< size; j++) { // in your case you have a size*size array, 
        fscanf(fptr, "%d,%d,%f", array[i][j]->tax, array[i][j]->savings, array[i][j]->salary);
     }
}

Вам необходимо решить, нужен ли вам одномерный или двумерный массив.

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