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
相关产品推荐
相关产品推荐

