C语言中scanf()后调用gets()、scanf("%c")无法接收输入问题咨询
问题分析与解决
根本原因:输入缓冲区残留换行符
你遇到的两个异常本质是同一个底层逻辑导致的:C语言所有标准输入函数共享同一个输入缓冲区,不同函数对空白字符(换行、空格、制表符等)的处理规则不同,导致前一次输入的残留字符被后一个函数误读取。
scanf("%s")读取字符串时,只会读取空白符之前的有效内容,会把触发输入结束的换行符\n遗留在输入缓冲区中gets()函数的逻辑是只要读到换行符就立刻结束读取,并且将换行符替换为字符串结束符\0。当它紧跟在scanf("%s")之后调用时,会直接读取到缓冲区里残留的\n,直接返回空内容,看起来就像没有接收用户输入一样。- 同理
scanf("%c")是读取任意单个字符,包括空白符,所以也会直接把残留的\n当成有效输入读走,不会等待用户输入新内容。
解决方法
1. 清理缓冲区残留的空白符
在scanf调用之后、调用gets/scanf("%c")之前,主动把缓冲区里的残留换行符清除,两种常用方案:
- 调用一次
getchar()读取掉残留的换行符,适合确定只残留了一个换行的场景 - 用
while(getchar()!='\n');循环清空缓冲区所有残留内容,适合残留内容不确定的场景
2. 针对scanf("%c")的简易处理
在%c前面加一个空格,写成scanf(" %c", &ch);,这个空格会告诉scanf自动跳过所有前置的空白字符,再读取有效字符。
3. 废弃gets()函数,替换为更安全的fgets()
gets()因为没有边界检查,非常容易造成缓冲区溢出漏洞,早在C11标准就被正式移除了,推荐用fgets(add, sizeof(add), stdin);替代,功能和gets一致但有长度保护。
修改后的可运行示例代码
#include<stdio.h> #include<conio.h> #include<string.h> void main(){ char username[25],Email[40],contact[15],add[80]; clrscr(); printf("Enter all your details below\n"); printf("username :"); scanf("%s", username); // 清空缓冲区残留的换行符 while(getchar() != '\n'); printf("Enter your Address:"); fgets(add, sizeof(add), stdin); // fgets会把读到的换行符存进字符串,不需要的话可以手动去掉 add[strcspn(add, "\n")] = '\0'; printf("Email ID :"); scanf("%s",Email); while(getchar() != '\n'); printf("Contact :"); scanf("%s",contact); while(getchar() != '\n'); printf("\nYour username is %s\n",username); printf("Your Email ID is %s\n",Email); printf("Your Contact No. is %s\n",contact); printf("Your Address is %s\n",add); getch(); }
内容的提问来源于stack exchange,提问作者Kaif Bhombal
相关产品推荐
相关产品推荐

