您的位置:首页 > 其它

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

2015-09-15 15:51 288 查看
版权归博主所有,转载请注明出处

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

int fflush(FILE<
dbbc
/span> *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;

}

                                                                                                                                                                                                                                                    步步为营,稳扎稳打
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: