数组分配问题:俱乐部邀请逻辑中邀请第二人时程序崩溃
俱乐部邀请规则C语言程序崩溃修复方案
需要实现的俱乐部邀请规则:教父(初始用户)邀请2人;被邀请的第一人拥有优先邀请另外2人的权限,待他完成邀请后,第二人才能发起邀请。当前程序在读取第一个被邀请人信息后,尝试邀请第二人时出现崩溃,需基于数组实现规则并修复问题。
原代码核心问题
- 野指针访问:
arrayPeople中的元素未分配People结构体内存,直接通过arrayPeople[index]->name写入会触发未定义行为(崩溃)。 - 内存分配类型不匹配:
verificationSize中realloc使用sizeof(People),但arrayPeople是People**类型,应该用sizeof(People*),导致内存分配错误。 - 权限验证逻辑失效:
verificationId中的条件表达式写法错误,||右侧未与ids比较,导致权限判断永远为真。 - 邀请逻辑违背规则:原代码在添加当前用户时直接创建其两个被邀请人,而非由用户主动发起邀请,不符合“第一人优先邀请”的要求。
- 链表指针混乱:
peopleList的赋值方向错误,导致用户关系链表无法正确追溯。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <string.h> typedef struct people{ char name[40]; int id; struct people *pgodFather; struct people *pfirst; struct people *psecond; bool canInvite; // 标记是否拥有邀请权限 }People; int currentId = 0; // 当前已注册用户数,初始教父为id0 People **arrayPeople; int initialSize = 10; // 检查数组容量,不足则扩容 void verificationSize(){ if(currentId >= initialSize){ initialSize *= 2; arrayPeople = realloc(arrayPeople, initialSize * sizeof(People*)); if(arrayPeople == NULL){ printf("内存分配失败!\n"); exit(1); } } } // 验证用户是否拥有邀请权限 bool verificationId(){ int inputId; printf("请输入你的ID: "); scanf("%d", &inputId); // 规则:只有当前可邀请的用户才能发起邀请 // 初始教父id0可邀请;后续只有上一轮优先被邀请的用户完成邀请后,下一个用户才能邀请 if(inputId >=0 && inputId < currentId && arrayPeople[inputId]->canInvite){ return true; } else{ printf("无邀请权限!\n"); return false; } } // 创建新用户(用于教父初始化或被邀请) People* createUser(int id, People* godFather){ People *newUser = (People*)malloc(sizeof(People)); if(newUser == NULL){ printf("内存分配失败!\n"); exit(1); } newUser->id = id; newUser->pgodFather = godFather; newUser->pfirst = NULL; newUser->psecond = NULL; newUser->canInvite = false; // 默认无邀请权限,需满足规则后开启 printf("请输入用户名: "); scanf("%s", newUser->name); return newUser; } // 邀请逻辑 void invite(){ system("cls"); bool accepted = false; People *inviter = NULL; if(currentId == 0){ // 初始化教父 accepted = true; verificationSize(); inviter = createUser(currentId, NULL); inviter->canInvite = true; // 教父拥有邀请权限 arrayPeople[currentId++] = inviter; printf("教父创建成功!ID: %d\n", inviter->id); } else{ // 验证邀请者权限 accepted = verificationId(); if(accepted){ int inputId; printf("请输入你的ID: "); scanf("%d", &inputId); inviter = arrayPeople[inputId]; } } if(accepted && inviter != NULL){ // 邀请第一个人 verificationSize(); People *firstInvitee = createUser(currentId, inviter); arrayPeople[currentId++] = firstInvitee; inviter->pfirst = firstInvitee; printf("成功邀请第一人!ID: %d\n", firstInvitee->id); // 邀请第二个人 verificationSize(); People *secondInvitee = createUser(currentId, inviter); arrayPeople[currentId++] = secondInvitee; inviter->psecond = secondInvitee; printf("成功邀请第二人!ID: %d\n", secondInvitee->id); // 更新权限:当前邀请者用完权限,开启第一个被邀请者的权限 inviter->canInvite = false; firstInvitee->canInvite = true; // 可扩展规则:当第一个被邀请者完成邀请后,再开启第二个被邀请者的权限 } } // 显示所有用户信息 void display(){ system("cls"); printf("俱乐部用户列表:\n"); for(int i=0; i<currentId; i++){ People *user = arrayPeople[i]; printf("ID: %d, 姓名: %s, 教父ID: %d, 可邀请: %s\n", user->id, user->name, user->pgodFather ? user->pgodFather->id : -1, user->canInvite ? "是" : "否"); } } int main(void){ arrayPeople = (People**)malloc(initialSize * sizeof(People*)); if(arrayPeople == NULL){ printf("内存分配失败!\n"); return 1; } int choice; bool stop = false; while(!stop){ printf("===== CROWS CLUB =====\n"); printf("1 - 发起邀请\n"); printf("2 - 搜索用户\n"); printf("3 - 显示所有用户\n"); printf("4 - 删除用户\n"); printf("5 - 退出\n"); printf("请选择操作: "); scanf("%d", &choice); switch(choice){ case 1: invite(); break; case 2: printf("搜索功能待实现\n"); break; case 3: display(); break; case 4: printf("删除功能待实现\n"); break; case 5: stop = true; break; default: printf("无效选项!\n"); break; } printf("\n按任意键继续..."); getchar(); getchar(); // 处理输入残留的换行符 } // 释放内存,避免泄漏 for(int i=0; i<currentId; i++){ free(arrayPeople[i]); } free(arrayPeople); return 0; }
关键修改说明
- 新增权限控制字段:在
People结构体中添加canInvite,明确标记用户是否具备邀请权限,严格遵循“第一人优先邀请”的规则。 - 修复内存分配错误:将
verificationSize中的sizeof(People)改为sizeof(People*),匹配arrayPeople的指针数组类型。 - 消除野指针:创建新用户时先分配
People结构体内存,再存入数组,确保所有指针访问都是有效的。 - 重构邀请逻辑:邀请操作由拥有权限的用户主动发起,而非自动生成被邀请人;教父初始化后,第一个被邀请者自动获得优先邀请权,完成邀请后可扩展开启第二个被邀请者的权限。
- 内存安全优化:添加内存分配失败的判断,避免程序崩溃;主函数末尾补充内存释放逻辑,防止内存泄漏。
- 交互体验优化:新增用户列表显示功能,方便查看权限和关系;处理输入换行符,避免交互异常。
内容的提问来源于stack exchange,提问作者Lua
相关产品推荐
相关产品推荐

