【问题标题】:C : Realloc doesn't work with dynamic double pointer arrayC:Realloc 不适用于动态双指针数组
【发布时间】:2020-07-26 23:37:34
【问题描述】:

我面临一些关于使用双指针动态数组重新分配的问题。 我想要执行的是在 type Flightarray 时间表中添加 2 个 type Flight* 的指针 **。

为此,我依赖于 Functions.c 文件中的函数 add_flight。 此函数向用户询问航空公司和航班号值,并将这些数据存储在新的Flight* f 中。如果时间表为 null(尚未添加航班),则它为新创建的航班分配内存,否则它重新分配时间表的大小以便添加新航班。

Main.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;
}

Functions.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;
}

在 main.c 中第二次调用 add_flight 时出现问题

add_flight函数中,数据确实存储在新的Flight* f中,然后考虑else语句:变量numberFlights取值为2。但是,realloc不起作用,时刻表没有放大,因此这个时刻表数组中仍然只存储了第一个航班。我不明白为什么第二个航班没有添加到时间表中。

有人能解释一下为什么这个 realloc 会失败吗? 谢谢你的帮助:)

【问题讨论】:

  • 使用malloc(sizeof(Flight*),您将保留指针大小的空间,要使用struct 本身的大小,请使用malloc(sizeof(Flight)) 或更好:malloc(sizeof *f)
  • 使用sizeof 运算符无法判断动态数组中有多少航班。您必须以不同的方式跟踪航班数量,例如使用额外变量或在所有航班结束时附加一个特殊的哨兵值。 (sizeof 运算符在此处在编译时进行评估,但您当然想知道在运行时有多少航班。)
  • @MOehm 感谢您的回答,我添加了一个变量 numberOfFlights,每次添加航班时它都会增加。但是还是不行,第二个航班没有添加

标签: c dynamic-memory-allocation allocation dynamic-arrays realloc


【解决方案1】:

sizeof 运算符在编译时进行评估。它不能用于确定动态分配数组的大小。

C 将跟踪数组实际大小的负担强加给了程序员。你可以保留一个单独的计数变量,但是因为实际的数组和它的大小属于一起,所以将它们并排存储在一个结构中是很有用的:

typedef struct Flight Flight;
typedef struct Flights Flights;

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

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

不是对数组进行操作,而是对结构进行操作:

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;
}

您可以在here 中看到它。一些观察:

  • 无需区分添加第一个和后续航班,因为realloc(NULL, size) 的行为与malloc(size) 完全相同。
  • 为每个添加的项目重新分配内存效率不是很高。相反,您选择一个合适的初始数组大小,如 4 或 8,然后在达到限制时将大小加倍。这意味着分配的大小和计数可能不同,您需要在航班结构中添加一个 memsize 字段。
  • 上面的代码依赖于手动初始化和销毁​​。通常,您将编写“构造函数”和“析构函数”函数来为您执行此操作。

【讨论】:

  • 非常感谢您的解释和帮助@MOehm!现在一切正常:)
  • 在我的说明中,我必须使用双指针以尽可能少地使用内存。因此,我对您的代码进行了一些修改:struct flight 现在具有指向 char 变量而不是 char 的指针。而且航班结构现在有变量 Flight** 航班而不是 Flight* 航班。但是,在函数 add_flight 中,我无法存储值,因为航班是双指针类型。我试过这个: fl->flight[n]->airline = _strdup(airline) 但它不起作用。你有什么想法让它发挥作用吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-06
  • 2013-02-12
  • 1970-01-01
相关资源
最近更新 更多