C/C++ 误区二:fflush(stdin)
当前位置:以往代写 > C/C++ 教程 >C/C++ 误区二:fflush(stdin)
2019-06-13

C/C++ 误区二:fflush(stdin)

C/C++ 误区二:fflush(stdin)

副标题#e#

1.为什么 fflush(stdin)是错的

首先请看以下措施:

include <stdio.h>

int main( void )

{

int i;

for ( ;;) {

fputs("Please input an integer: ", stdout);

scanf("%d", &i);

printf("%d\n", i);

}

return 0;

}

这个措施首先会提示用户输入一个整数,然后等 待用户输入,假如用户输入的是整数,措施会输出适才输入的整数,而且再次提 示用户输入一个整数,然后期待用户输入。可是一旦用户输入的不是整数(如小 数可能字母),假设 scanf 函数最后一次获得的整数是 2 ,那么措施会不断地 输出“Please input an integer: 2”。这是因为 scanf ("%d", &i); 只能接管整数,假如用户输入了字母,则这个 字母会遗留在“输入缓冲区”中。因为缓冲中有数据,故而 scanf 函数不会期待用户输入,直接就去缓冲中读取,但是缓冲中的却是字母,这个字 母再次被遗留在缓冲中,如此重复,从而导致不断地输出“Please input an integer: 2”。

也许有人会说:“居然这样,那么在 scanf 函数后头加上‘fflush(stdin);’,把输入缓冲清空掉不 就行了?”然而这是错的!C和C++的尺度里从来没有界说过 fflush (stdin)。也许有人会说:“但是我用 fflush(stdin) 办理了这个问 题,你怎么能说是错的呢?”简直,某些编译器(如VC6)支持用 fflush (stdin) 来清空输入缓冲,可是并非所有编译器都要支持这个成果(linux 下 的 gcc 就不支持),因为尺度中基础没有界说 fflush(stdin)。MSDN 文档里 也清楚地写着fflush on input stream is an extension to the C standard( fflush 操纵输入流是对 C 尺度的扩充)。虽然,假如你绝不在乎措施的移植性 ,用 fflush(stdin) 也没什么大问题。以下是 C99 对 fflush 函数的界说:

int fflush(FILE *stream);

假如 stream 指向输出流可能更 新流(update stream),而且这个更新流最近执行的操纵不是输入,那么 fflush 函数将把这个流中任何待写数据传送至宿主情况(host environment) 写入文件。不然,它的行为是未界说的。

原文如下:

int fflush (FILE *stream);

If stream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined.

个中,宿主情况可以领略为 操纵系统或内核等。

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


#p#副标题#e#

2. 清空输入缓冲区的要领

固然不行以用 fflush(stdin),可是我 们可以本身写代码来清空输入缓冲区。只需要在 scanf 函数后头加上几句简朴 的代码就可以了。

/* C 版本 */
#include <stdio.h>

int main( void )
{
int i, c;
for ( ; ; )
{
fputs("Please input an integer: ", stdout);
scanf("%d", &i);

if ( feof(stdin) || ferror(stdin) )
{ /* 假如用户输入文件竣事符号(或 文件已被读完), */
/* 可能产生读写错误,则退出轮回 */

/* do something */
break;
}
/* 没有产生错误,清空输入流。 */
/* 通过 while 轮回把输入流中的余留数据“吃”掉 */
while ( (c = getchar()) != '\n' && c != EOF ) ;
/* 利用 scanf("%*[^\n]"); 也可以清空输入流, */

/* 不外会残留 \n 字符。*/

printf("%d\n", i);
}

return 0;
}

/* C++ 版本 */
#include <iostream>
#include <limits> // 为了 利用numeric_limits

using std::cout;
using std::endl;
using std::cin;
using std::numeric_limits;
using std::streamsize;

int main()
{
int value;
for ( ; ; )
{
cout << "Enter an integer: ";
cin >> value;
if ( cin.eof() || cin.bad() )
{ // 假如用户输入文件竣事符号(或文件已被读完),
// 可能产生读写错误,则退出轮回

// do something
break;
}
// 读到犯科字符后,输入流将处于堕落状态,
// 为了继承获取输入,首先要挪用 clear 函数
// 来排除输入流的错误标志 ,然后才气挪用
// ignore 函数来排除输入流中的数据。
cin.clear();
// numeric_limits<streamsize>::max() 返回输 入缓冲的巨细。
// ignore 函数在此将把输入流中的数据清空。
// 这两个函数的详细用法请读者自行查询。
cin.ignore( numeric_limits<streamsize>::max(), '\n' );

cout << value << '\n';
}

return 0;
}

    关键字:

在线提交作业