前言
scanf 和 getchar 等函数会在 stdin(标准输入缓冲区) 中读取数据,若上述缓冲区中已存在数据,则直接读取其中的数据,若缓冲区为空,则函数会挂起,等待数据缓冲的完成( 用户输入回车键或数据缓冲区满后, stdin 会进行数据缓冲,之后上述函数才能继续执行)。 用户一次输入的数据可能会超过 scanf 、getchar 等函数调用所需要的数据,那么所需数据被读取后,剩余的数据仍会存放在缓冲区中,之后的函数调用会直接读取 stdin 中已有的数据。只有当缓冲区为空后,scanf 等函数才会等待用户输入(实际应该是等待 stdin 的缓冲)。
一、scanf的数据匹配问题
scanf函数从缓冲区读取整型数,浮点数,字符串时,会忽略回车符('\n') ,空格等字符,在读取单个字符时不会忽略任何字符(一般问题就是结束输入的回车符被下一个字符读取)。匹配之后的数据要从缓冲区中删除。
二、问题实例
1.连续输入
如1a2.0qwer
#include <stdio.h>
int main()
{
//整型数a,字符c,浮点数f,字符串str(可看做字符串)
int a;
char c;
float f;
char str[20];
scanf("%d",&a);
scanf("%c",&c);
scanf("%f",&f);
scanf("%s",&str);//
printf("a=%d,c=%c,f=%f,str=%s\n",a,c,f,str);
我们会得到正常结果
a=1,c=a,f=2.0,str=qwer
2.间隔输入
如1(回车)a(回车)2.0(回车)qwer(回车)
出现明显错误,缓冲区的数据变成了 1 回车 a 回车 ,分别对应我们四个变量,1赋值给了a,回车符给了c,f为浮点数据,没有匹配到直接输出地址,a赋给了str,剩下的数据继续留在缓存区留待下次读取,这是非常不好的情况
3.规则输入
根据匹配规则我们知道,只有字符型数据可以读取回车空格等字符,所以我们在c后加回车,即1a(回车)2.0(回车)qwer(回车),浮点和字符串不读取回车符号,所以不用担心,这样我们也可以做到正确输入
总结以及清除缓存
我们得知了缓存区的基本原理,但是我们正常是不可能考虑这么多的,所以我们最好做到清除缓存
1.使用getchar+while :
使用 while(getBuff=getchar()!=‘\n’ && getBuff!=EOF),使用循环把缓冲区的读完,直到读到缓冲区的\n或者是空值
2.使用gets+预留最大值成功:
使用gets,创建一个数组,将缓冲区的内容读完 。
以上两种都是使用流的方式,将缓存区读完。