C语言realloc动态数组扩容失效,无法添加多名Player问题求助
问题分析与修复方案
核心错误点
- 指针算术使用错误:
temp+(sizeof(Player)*addedPlayerCounter)写法错误。C语言中指针做加法时,编译器会自动将偏移量乘以指针指向类型的大小,这里多做了一次sizeof计算,导致越界访问,无法正确存储后续Player数据。 - 未更新Team的players指针:
realloc后得到的新指针temp没有赋值给team->players,导致Team始终持有初始的NULL指针,后续扩容操作相当于每次都重新从NULL分配,之前添加的Player数据全部丢失。 - Player字段复制不完整:仅复制了
playerName和pointsAverage,遗漏了uniformNumber和pointsOfLastFiveGames字段,数据不完整。 - 内存泄漏:
setPlayer返回的动态分配的tempPlayer没有释放,每次添加Player都会产生内存泄漏。 - 结构体初始化语法错误:C语言不支持在结构体定义中直接给成员赋初始值(
char *managerName = nullptr;),这是C++语法,会导致编译失败。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #define NUM_OF_PLAYER_POINT 5 // 补充缺失的宏定义 struct Player { float pointsAverage; int uniformNumber; int pointsOfLastFiveGames[5]; char *playerName; }; struct Team { int numberOfPlayers; char *managerName; struct Player *players; }; struct Player* setPlayer(){ struct Player *player = (struct Player*)malloc(sizeof(struct Player)); if (!player) { // 增加内存分配失败检查 perror("malloc failed for Player"); exit(EXIT_FAILURE); } char name[81] = {0}; int jerseyNumber = -1; int sumOfPoints = 0; int currentPoint = 0; printf("Player name?\n"); scanf("%s", name); // name本身是指针,无需& int nameLength = strlen(name); player->playerName = (char*)malloc(sizeof(char)*(nameLength + 1)); if (!player->playerName) { perror("malloc failed for player name"); free(player); exit(EXIT_FAILURE); } strcpy(player->playerName, name); printf("Jersey number?\n"); scanf("%d",&jerseyNumber); player->uniformNumber = jerseyNumber; printf("Player point history?\n"); int i; for (i=0; i<NUM_OF_PLAYER_POINT; i++) { scanf("%d",¤tPoint); player->pointsOfLastFiveGames[i] = currentPoint; // 保存每场分数 sumOfPoints+=currentPoint; } player->pointsAverage = (float)sumOfPoints / NUM_OF_PLAYER_POINT; // 修正整数除法精度问题 return player; } struct Team* setTeam(){ struct Team *team = (struct Team*) malloc(sizeof(struct Team)); if (!team) { perror("malloc failed for Team"); exit(EXIT_FAILURE); } team->managerName = NULL; team->numberOfPlayers = 0; team->players = NULL; int usersChoice = -1; char name[81] = {0}; printf("Hello, please enter manager's name:\n"); scanf("%s", name); // 去掉多余的& int nameLength = strlen(name); team->managerName = (char *)malloc(sizeof(char) * (nameLength + 1)); if (!team->managerName) { perror("malloc failed for manager name"); free(team); exit(EXIT_FAILURE); } strcpy(team->managerName, name); while (1){ printf("Would you like to buy a player (1) yes (else) no?\n"); scanf("%d",&usersChoice); if(usersChoice==1){ struct Player* tempPlayer = setPlayer(); // 扩容到当前人数+1的大小 struct Player *temp = (struct Player*)realloc(team->players, sizeof(struct Player)*(team->numberOfPlayers + 1)); if (!temp) { perror("realloc failed for players"); // 分配失败时释放tempPlayer避免泄漏 free(tempPlayer->playerName); free(tempPlayer); exit(EXIT_FAILURE); } team->players = temp; // 更新Team的players指针 // 复制tempPlayer所有字段到新位置 team->players[team->numberOfPlayers] = *tempPlayer; // 释放tempPlayer,内容已复制到team的数组中 free(tempPlayer); team->numberOfPlayers++; }else{ return team; } } } // 主函数示例 int main() { struct Team *myTeam = setTeam(); // 后续可添加打印Team信息的代码 // 记得最后释放所有动态分配的内存避免泄漏 return 0; }
额外优化说明
- 增加内存分配失败检查,避免空指针访问。
- 修正
setPlayer中整数除法的精度问题,改为先转float再执行除法。 - 简化计数逻辑,直接用
team->numberOfPlayers跟踪当前玩家数量,减少冗余变量。 - 修复
scanf("%s", &name)的错误,数组名本身就是指针,无需取地址符&。
内容的提问来源于stack exchange,提问作者NoobProgrammer
相关产品推荐
相关产品推荐

