C: Reallo c не работает с динамическим c массивом двойных указателей - PullRequest
0 голосов
/ 14 апреля 2020

Я сталкиваюсь с некоторыми проблемами, касающимися reallo c с массивом динамиков с двойным указателем c. Я хотел бы выполнить добавить 2 указателя типа Flight * внутри массива расписания Flight **.

Для этого я использую функцию add_flight в файле Functions. c. Эта функция запрашивает у пользователя значения авиакомпании и номера рейса и сохраняет эти данные в новом Flight* f. Если расписание равно null (еще не добавлено ни одного рейса), оно выделяет память для вновь созданного рейса, в противном случае оно reallo c размер расписания для добавить новый рейс.

Основной. c файл:

int main() {
    int choice = 1;
    Flight** schedule = NULL;   

    printf("---AIRPORT MANAGER---");
    schedule = add_flight(schedule);
    printf("\n%s : %d\n", (*schedule)->airline, (*schedule)->flightNumber);
    schedule = add_flight(schedule);
    printf("\n%s : %d\n", (*schedule + 1)->airline, (*schedule)->flightNumber);

    return 0;
}

Функции. c файл:

#include "Functions.h"

void mygets(char* s, int maxLength) {
    fflush(stdout);
    if (fgets(s, maxLength, stdin) != NULL) {
        size_t lastIndex = strlen(s) - 1;
        if (s[lastIndex] == '\n')
            s[lastIndex] = '\0';
    }
}

void flush() {
    char buffer;
    while ((buffer = getchar()) != EOF && buffer != '\n');
}

Flight** add_flight(Flight** schedule) {
    Flight* f;
    char buffer[100];

    if ((f = (Flight*)malloc(sizeof(Flight*))) == NULL) {
        exit(1);
    }

    printf("\n\n---FLIGHT CREATION---");
    printf("\nAirline: ");
    mygets(buffer, sizeof(buffer));
    if ((f->airline = _strdup(buffer)) == NULL) {
        exit(1);
    }
    memset(buffer, 0, 100);

    printf("\nFlight number: ");
    scanf("%d", &f->flightNumber);
    flush();

    if (schedule == NULL) {
        if ((schedule = malloc(sizeof(Flight*))) == NULL) {
            exit(1);
        }       
        *schedule = f;
    }
    else {
        int numberFlights = ((sizeof(*schedule)) / 4) + 1;
        if ((schedule = realloc(schedule, numberFlights * sizeof(Flight*))) == NULL) {
            exit(1);
        }
        *(schedule + numberFlights -1) = f;
    }

    return schedule;
}

Проблема возникает, когда второй вызов add_flight выполняется в основном. c

В функции add_flight данные действительно сохраняются в новом Flight* f и затем рассматривается оператор else: переменная numberFlights получает значение 2. Однако reallo c не работает , расписание не увеличено и, таким образом, существует все еще только первый полет, сохраненный в этом массиве расписания. Я не могу понять, почему второй рейс не добавлен в расписание.

Может кто-нибудь объяснить мне, почему этот reallo c не срабатывает? Спасибо за вашу помощь:)

1 Ответ

0 голосов
/ 14 апреля 2020

Оператор sizeof вычисляется во время компиляции. Его нельзя использовать для определения размера динамически размещаемого массива.

C накладывает бремя отслеживания фактического размера массива на программиста. Вы можете сохранить отдельную переменную count, но поскольку фактический массив и его размер принадлежат друг другу, полезно хранить их рядом друг с другом в структуре:

typedef struct Flight Flight;
typedef struct Flights Flights;

struct Flight {
    char airline[4];
    int number;
    char dest[4];
};

struct Flights {
    Flight *flight;
    int count;
};

Вместо того, чтобы работать с массивом, работайте с the struct:

void add_flight(Flights *fl,
    const char *airline, int number, const char *dest)
{
    int n = fl->count++;        // n is old count; fl->count is new count

    fl->flight = realloc(fl->flight,
        (fl->count + 1) * sizeof(*fl->flight));

    snprintf(fl->flight[n].airline, 4, "%s", airline);
    snprintf(fl->flight[n].dest, 4, "%s", dest);
    fl->flight[n].number = number;
}

Инициализировать структуру рейсов с помощью NULL с нулевым счетом и не забудьте освободить использованную память, когда закончите:

int main(void)
{
    Flights fl = {NULL, 0};

    add_flight(&fl, "AF", 5512, "CDG");
    add_flight(&fl, "AA", 1100, "ATL");
    add_flight(&fl, "LH", 6537, "FRA");
    add_flight(&fl, "BA", 8821, "LHR");
    add_flight(&fl, "IB", 1081, "EZE");

    print_flights(&fl);

    free(fl.flight);

    return 0;
}

Вы можете увидеть это в действии здесь . Некоторые наблюдения:

  • Нет необходимости различать guish между добавлением первого и последующих полетов, поскольку realloc(NULL, size) ведет себя точно так же, как malloc(size).
  • Это не очень эффективно перераспределять память для каждого добавленного элемента. Вместо этого вы выбираете подходящий начальный размер массива, например 4 или 8, а затем удваиваете размер при достижении предела. Это означает, что выделенный размер и количество могут отличаться, и вам нужно дополнительное поле memsize в структуре ваших рейсов.
  • Приведенный выше код основан на ручной инициализации и уничтожении. Обычно вы будете писать функции «конструктор» и «деструктор», чтобы сделать это для вас.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...