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

嵌套结构体数组为何会覆盖已存储值?

问题原因分析
  • 未初始化的指针nm
    代码中char *nm;仅声明了指针,但未分配任何内存空间,也未指向有效的内存区域。调用fgets(nm, 30, stdin)时,属于访问未定义内存,行为完全不可控——可能直接程序崩溃,也可能数据被写入随机区域,导致后续无法正确读取。

  • 所有投票者的name指向同一块内存(即使nm初始化)
    就算给nm分配了固定内存,每次输入都复用同一个缓冲区,再把这个指针赋值给不同的voterDetails[i].name,所有结构体的name字段都会指向同一块内存。新输入的名字会直接覆盖旧内容,导致之前存储的名字被冲掉,看起来像是没保留。

  • scanf残留换行符导致输入异常
    scanf("%d", &choice)读取整数后,输入缓冲区会残留一个换行符。第一个fgets会直接读取这个换行符,得到空字符串,第二个fgets才是实际输入的名字。这会导致第一次存储的内容不符合预期,甚至出现空值。

修复方案
  • 为每个投票者的name单独分配内存
    不要复用同一个缓冲区,而是每次输入后为对应投票者的name字段分配独立内存并复制字符串,避免覆盖:

    // 替换原char *nm;为临时缓冲区
    char tempName[30];
    // 输入名字
    fgets(tempName, 30, stdin);
    // 去除fgets读入的换行符
    tempName[strcspn(tempName, "\n")] = '\0';
    // 分配内存并复制字符串
    temp->voterDetails[voteNum-1].name = malloc(strlen(tempName) + 1);
    strcpy(temp->voterDetails[voteNum-1].name, tempName);
    
  • 处理scanf后的残留换行符
    在scanf读取选择后,用getchar()丢弃缓冲区里的换行符,这样后续的fgets就能直接读取输入的名字,不需要两次调用:

    scanf("%d", &choice);
    getchar(); // 吃掉换行符
    
  • 添加数组越界检查
    每次投票前检查voteNum是否已达到5(voterDetails的最大容量),避免非法访问内存:

    case 1:
        if(voteNum >=5){
            printf("当前区块已无剩余投票名额\n");
            break;
        }
        // 后续输入逻辑
    

内容的提问来源于stack exchange,提问作者Syed Muhammad Taha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 19:01:52