C : Realloc 不适用于动态双指针数组
C : Realloc doesn't work with dynamic double pointer array
我遇到了一些关于使用双指针动态数组重新分配的问题。
我想要执行的是 add 2 pointers of type Flight* inside the array schedule of 类型航班 **.
为此,我依赖 Functions.c 文件中的函数 add_flight
。
此函数要求用户提供航空公司和航班号值,并将这些数据存储在新的 Flight* f
中。如果计划是 null(尚未添加航班),它会 为新创建的航班分配 内存,否则它会 realloc 计划的大小,以便添加新航班。
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] = '[=11=]';
}
}
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 失败了?
感谢您的帮助:)
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
字段。
- 以上代码依赖于手动初始化和销毁。通常,您会编写 "constructor" 和 "destructor" 函数来为您完成此操作。
我遇到了一些关于使用双指针动态数组重新分配的问题。 我想要执行的是 add 2 pointers of type Flight* inside the array schedule of 类型航班 **.
为此,我依赖 Functions.c 文件中的函数 add_flight
。
此函数要求用户提供航空公司和航班号值,并将这些数据存储在新的 Flight* f
中。如果计划是 null(尚未添加航班),它会 为新创建的航班分配 内存,否则它会 realloc 计划的大小,以便添加新航班。
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] = '[=11=]';
}
}
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 失败了? 感谢您的帮助:)
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
字段。 - 以上代码依赖于手动初始化和销毁。通常,您会编写 "constructor" 和 "destructor" 函数来为您完成此操作。