最近老陌偶然从论坛的一个帖子里发现了以前忽略了的一个知识点,看了一些资料后不得不感慨自己之前对于 scanf 对于 C 的理解实在太浅显了!最后我打算把本次学习所得写出来……
double get_input(void)
{
double a;
char ch;
while(scanf("%lf",&a)!=1)
{
while ((ch=getchar())!='\n')
putchar(ch);
printf("\nEnter a number\n");
}
return a;
}
while(scanf("%lf",&a)!=1) // 输入的是double内容,那么while循环体不执行; 如果不是double,键盘缓冲区的内容并没有变化,还是原来的内容,所以一直在这儿死循环
while(scanf("%lf",&a)!=1) { // 输入的不是一个double类型数据, 会进入这个while循环体
while ((ch=getchar())!='\n') // 把缓冲区的字符一个一个的提取出来, 包括最后的回车符, 也就是放弃了这一整行的数据了
后面的这个函数,因为可以把键盘缓冲区清空,让用户重新输入数据,所以可以继续进行下去
前面的那个函数,因为没有清理缓冲区, 所以读取double的条件始终无法达到
C标准规定 fflush()函数是用来刷新输出(stdout)缓存的。对于输入(stdin),它是没有定义的。但是有些编译器也定义了 fflush( stdin )的实现,比如微软的VC。其它编译器是否也定义了 fflush( stdin )的实现应当查找它的手册。GCC编译器没有定义它的实现,所以不能使用 fflush( stdin )来刷新输入缓存。
对于没有定义 fflush( stdin )的编译器,可以使用 fgets()函数来代替它(比用 getchar()、scanf()等函数通用性好)。可以这样忽略输入流中留下的回车等其它输入,从而使下一次的输入总保持一个“干净”的状态。(这个是任何平台下都可以的)
功能:清空输入缓冲区,通常是为了确保不影响后面的数据读取(例如在读完一个字符串后紧接着又要读取一个字符,此时应该先执行fflush(stdin);)。
fflush(stdin)仅适用于部分编译器(如VC6),但是并非所有编译器都要支持这个功能(如gcc3.2)。这是一个对C标准的扩充。在linux下用的是gcc,因此可能不起作用。
键盘的内部有一块微处理器,它控制着键盘的全部工作,比如主机加电时键盘的自检、扫描,扫描码的缓冲以及与主机的通讯等等。当一个键被按下时,微处理器便根据其位置,将字符信号转换成二进制码,传给主机和显示器。如果操作人员的输入速度很快或CPU正在进行其它的工作,就先将键入的内容送往内存中的键盘缓冲区,等CPU空闲时再从缓冲区中取出暂存的指令分析并执行
scanf支持正则
scanf(“%*[^\n]%*c”);
参考资料: