You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

动态分配结构体数组异常:输入乱码与scanf语句跳过问题

问题分析与解决方案

嘿,你的问题根源在于输入缓冲区的残留字符在捣乱,导致fgetsscanf的读取顺序彻底混乱,才会出现随机字符、跳过输入的情况。我给你拆解清楚问题,再提供两种靠谱的修复方案:

核心问题点

  1. 读取size后的换行残留:当你用scanf("%d", &size)读完数组大小后,你按下的回车会留在输入流里。接下来第一个fgets会直接读取这个空的换行符,导致members[i].name被设置成空字符串,后续的scanf("%c %d")就会把原本应该是名字的字符错当成rank,自然出现乱码。
  2. %c的读取特性scanf("%c %d")里的%c会匹配任何字符(包括空格、换行),如果前面的输入残留没清理,很容易读取到非预期的字符,进一步打乱输入流程。

修复方案

方式一:手动清理输入缓冲区

在关键节点清理输入流里的残留换行,确保每个读取函数都能拿到正确的输入:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
    struct DEP {
        char name[30];
        char rank;
        int number;
    };
    struct DEP *members;
    int size, i;
    scanf("%d", &size);
    // 吃掉scanf读size后残留的换行符
    getchar();
    members = malloc(size * sizeof(struct DEP));
    if(members == NULL) {
        return 1;
    }
    for(i = 0;i < size;i++) {
        fgets(members[i].name, 30, stdin);
        members[i].name[strcspn(members[i].name, "\n")] = '\0';
        // %c前加空格,自动跳过所有空白字符(空格、换行、制表符)
        scanf(" %c %d", &members[i].rank, &members[i].number);
        // 再次清理scanf后的换行,保证下一轮fgets正常工作
        getchar();
        printf("%s\n%c\n%d\n", members[i].name, members[i].rank, members[i].number);
    }
    free(members); // 别忘了释放动态分配的内存,避免泄漏!
    return 0;
}

方式二:统一用fgets读取(更安全)

避免混用scanffgets,统一按行读取输入后再解析,彻底杜绝缓冲区残留问题:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
    struct DEP {
        char name[30];
        char rank;
        int number;
    };
    struct DEP *members;
    int size, i;
    char buffer[100]; // 临时存储整行输入
    
    // 先读size所在的行,再解析出数字
    fgets(buffer, sizeof(buffer), stdin);
    sscanf(buffer, "%d", &size);
    
    members = malloc(size * sizeof(struct DEP));
    if(members == NULL) {
        return 1;
    }
    
    for(i = 0;i < size;i++) {
        // 读取名字行
        fgets(members[i].name, 30, stdin);
        members[i].name[strcspn(members[i].name, "\n")] = '\0';
        
        // 读取rank和number所在的行,再解析
        fgets(buffer, sizeof(buffer), stdin);
        sscanf(buffer, "%c %d", &members[i].rank, &members[i].number);
        
        printf("%s\n%c\n%d\n", members[i].name, members[i].rank, members[i].number);
    }
    free(members);
    return 0;
}

测试示例

比如输入:

2
JOHN
A 123
MIKE
B 456

修复后的代码会正确输出:

JOHN
A
123
MIKE
B
456

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

火山引擎 最新活动