scanf()导致死循环且fflush(stdin)无效详解

版权归博主所有,转载请注明出处

scanf(const char *format, ......):根据参数format字符串格来格式化标准输入数据到指定内存,format具体使用方法可以参考printf().

注意点:

1、多个参数时,不同参数间可以用空格隔开,也可以用回车隔开,但是只有回车表示结束。

2、当输入参数与格式不对时,函数内部会自动调到下一个输入数据,并比对对应数据是否与格式匹配,不匹配则又调到下一个输入数据,直到匹配或者没有数据,scanf返回值即为匹配成功了的数据个,通过返回值即可判断用户输入是否正常。

3、匹配时跳过的数据不会被系统清空,会依然保留在缓存区,所以此时可能会出现如下情况:

a、没有输入完所有参数,scanf就返回了;

b、scanf一直返回,没有等待用户重新输入,即可能出现死循环。

4、解决 出现第3种情况的办法:

a、使用getchar函数将缓存区里面的数据全部读出,这个方法需确切知道用户输入了多少无效的数据,可用性不强;

b、使用fgets()函数替代getchar(),可以一次性刷新错误缓存数据,保证用户第二次输入重新按干净的环境开始,可用性超强;

b、使用fflush()函数清除缓存:使用ffulsh()时,请不要使用fflush(stdin),因为fflush(stdin)移植性不好,有的平台在会无效,且这个行为是不确定的。

也许有人会说:“居然这样,那么在 scanf 函数后面加上‘fflush(stdin);,把输入缓冲清空掉不就行了?”然而这是错的!CC++标准里从来没有定义过 fflush(stdin)。也许有人会说:“可是我用 fflush(stdin) 解决了这个问题,你怎么能说是错的呢?”的确,某些编译器(如VC6)支持用 fflush(stdin) 来清空输入缓冲,但是并非所有编译器都要支持这个功能(gcc3.2不支持),因为标准中根本没有定义 fflush(stdin)MSDN 文档里也清楚地写着fflush on input stream is anextension to the C standardfflush 操作输入流是对 C 标准的扩充)。当然,如果你毫不在乎程序的移植性,用
fflush(stdin) 也没什么大问题。以下是 C99  fflush 函数的定义:

int fflush(FILE *stream);

如果stream指向输出流或者更新流update stream),并且这个更新流
最近执行的操作不是输入,那么fflush函数将把任何未被写入的数据写入stream
指向的文件(如标准输出文件stdout)。否则,fflush函数的行为是不确定的。
fflush(NULL)清空所有输出流和上面提到的更新流。如果发生写错误,fflush
函数会给那些流打上错误标记,并且返回EOF,否则返回0。

由此可知,如果 stream 指向输入流(如 stdin),那么 fflush 函数的行为是不确定的。故而使用
fflush(stdin) 是不正确的,至少是移植性不好的。


SampleCode:


#include <stdio.h>
#include <string.h>
#include <signal.h>
char main_qiut = 0;
void SignalHandlerSetQuit(int sig)
{
printf("Recv signal is %d\n", sig);
signal(SIGSEGV, SIG_DFL);
main_quit = 1;
printf("Please input any key and Enter to exit......\n");
}


int main(int argc, char *argv[])
{
singal(SIGINT,  SignalHandlerSetQuit);
singal(SIGBUS,  SignalHandlerSetQuit);
singal(SIGTERM, SignalHandlerSetQuit);
singal(SIGSEGV, SignalHandlerSetQuit);
singal(SIGILL,  SignalHandlerSetQuit);
singal(SIGPIPE, SIG_IGN);
int x = 0, y = 0,z = 0, ret = 0;
char err_input[128] = "";


for(;;)
{
printf("Please Three number......");
ret = scanf("%d%d%d",&x, &y, &z);
if(1 == main_quit)
{
return 0;
}
if(3 != ret)
{
printf("err key is %s\n", fgets(err_input, sizeof(err_input) - 1), stdin);
continue; //break;
}
printf("x=%d  y=%d  z=%d", x, y, z);
}
return 1;
}

                                                                                                                                                                                                                                                    步步为营,稳扎稳打

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值