You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

数组分配问题:俱乐部邀请逻辑中邀请第二人时程序崩溃

俱乐部邀请规则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;
}

关键修改说明

  1. 新增权限控制字段:在People结构体中添加canInvite,明确标记用户是否具备邀请权限,严格遵循“第一人优先邀请”的规则。
  2. 修复内存分配错误:将verificationSize中的sizeof(People)改为sizeof(People*),匹配arrayPeople的指针数组类型。
  3. 消除野指针:创建新用户时先分配People结构体内存,再存入数组,确保所有指针访问都是有效的。
  4. 重构邀请逻辑:邀请操作由拥有权限的用户主动发起,而非自动生成被邀请人;教父初始化后,第一个被邀请者自动获得优先邀请权,完成邀请后可扩展开启第二个被邀请者的权限。
  5. 内存安全优化:添加内存分配失败的判断,避免程序崩溃;主函数末尾补充内存释放逻辑,防止内存泄漏。
  6. 交互体验优化:新增用户列表显示功能,方便查看权限和关系;处理输入换行符,避免交互异常。

内容的提问来源于stack exchange,提问作者Lua

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 02:15:17