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

C语言循环中fgets()输入失效求助:fflush(stdin)未解决问题

问题排查:C语言录入学生信息时fgets循环输入异常

编写了一段用于录入3名学生信息的C语言代码,最初使用gets()时收到警告,改用fgets()后问题依旧:循环从第二次开始,姓名输入环节无法正常工作。猜测是缓冲区问题,但已使用fflush(stdin),恳请帮忙排查原因。代码如下:

#include <stdio.h>
#include <string.h>

struct student{
    char name[20];
    char studentNumber[5];
    int yearOfBirth;
    float avgPoint;
};

int main(){
    struct student hssv[3];
    int i;
//input info for students, this case its 3 students
    for(i=0; i<3; i++){
        printf("Input element value: ");
        printf("\nInput your name: ");
        fflush(stdin);
        fgets(hssv[i].name, sizeof(hssv[i].name), stdin); //this line doesnt work for the loop
        printf("Input your student code: ");
        fflush(stdin);
        fgets(hssv[i].studentNumber, sizeof(hssv[i].studentNumber), stdin);
        printf("Input your year of birth: ");
        scanf("%d", &hssv[i].yearOfBirth);
        printf("Input your point: ");
        scanf("%f", &hssv[i].avgPoint);
    }
//output info
    for(i=0; i<3; i++){
        printf("\nOutput element value: ");
        printf("\nYour name: %s", hssv[i].name);
        printf("\nInput your student code: %s", hssv[i].studentNumber);
        printf("\nInput your year of birth: %d", hssv[i].yearOfBirth);
        printf("\n\nInput your point: %f", hssv[i].avgPoint);
    }

    return 0;
}

核心原因

  • fflush(stdin)的未定义行为:C标准明确规定fflush()仅对输出流有效,对输入流(如stdin)调用属于未定义行为,不同编译器表现不一致,不能依赖它清空输入缓冲区。
  • scanf遗留的换行符:scanf("%d")和scanf("%f")读取数值时,只会提取对应的数字,用户输入的换行符会残留在缓冲区中。下一次调用fgets()时,会直接读取这个换行符作为有效输入,导致姓名输入环节“跳过”。

解决方案

方案一:手动清空scanf后的缓冲区

在每次scanf调用后,手动读取并丢弃缓冲区剩余字符,确保下一次fgets能正常读取用户输入:

#include <stdio.h>
#include <string.h>

struct student{
    char name[20];
    char studentNumber[5];
    int yearOfBirth;
    float avgPoint;
};

int main(){
    struct student hssv[3];
    int i;
    int c; // 用于读取缓冲区剩余字符

    for(i=0; i<3; i++){
        printf("Input element value: ");
        printf("\nInput your name: ");
        fgets(hssv[i].name, sizeof(hssv[i].name), stdin);
        // 去掉fgets读取的换行符,避免输出多空行
        hssv[i].name[strcspn(hssv[i].name, "\n")] = '\0';
        
        printf("Input your student code: ");
        fgets(hssv[i].studentNumber, sizeof(hssv[i].studentNumber), stdin);
        hssv[i].studentNumber[strcspn(hssv[i].studentNumber, "\n")] = '\0';
        
        printf("Input your year of birth: ");
        scanf("%d", &hssv[i].yearOfBirth);
        // 清空缓冲区直到换行符
        while((c = getchar()) != '\n' && c != EOF);
        
        printf("Input your point: ");
        scanf("%f", &hssv[i].avgPoint);
        // 再次清空缓冲区
        while((c = getchar()) != '\n' && c != EOF);
    }

    for(i=0; i<3; i++){
        printf("\nOutput element value: ");
        printf("\nYour name: %s", hssv[i].name);
        printf("\nYour student code: %s", hssv[i].studentNumber);
        printf("\nYour year of birth: %d", hssv[i].yearOfBirth);
        printf("\n\nYour point: %f", hssv[i].avgPoint);
    }

    return 0;
}

方案二:统一使用fgets读取所有输入(更安全)

避免混合使用scanf和fgets,统一用fgets读取整行输入,再通过sscanf()转换为数值类型,从根源上解决缓冲区问题:

#include <stdio.h>
#include <string.h>

struct student{
    char name[20];
    char studentNumber[5];
    int yearOfBirth;
    float avgPoint;
};

int main(){
    struct student hssv[3];
    int i;
    char buffer[50]; // 临时存储整行输入

    for(i=0; i<3; i++){
        printf("Input element value: ");
        printf("\nInput your name: ");
        fgets(hssv[i].name, sizeof(hssv[i].name), stdin);
        hssv[i].name[strcspn(hssv[i].name, "\n")] = '\0';
        
        printf("Input your student code: ");
        fgets(hssv[i].studentNumber, sizeof(hssv[i].studentNumber), stdin);
        hssv[i].studentNumber[strcspn(hssv[i].studentNumber, "\n")] = '\0';
        
        printf("Input your year of birth: ");
        fgets(buffer, sizeof(buffer), stdin);
        sscanf(buffer, "%d", &hssv[i].yearOfBirth);
        
        printf("Input your point: ");
        fgets(buffer, sizeof(buffer), stdin);
        sscanf(buffer, "%f", &hssv[i].avgPoint);
    }

    for(i=0; i<3; i++){
        printf("\nOutput element value: ");
        printf("\nYour name: %s", hssv[i].name);
        printf("\nYour student code: %s", hssv[i].studentNumber);
        printf("\nYour year of birth: %d", hssv[i].yearOfBirth);
        printf("\n\nYour point: %f", hssv[i].avgPoint);
    }

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 20:37:38