关于 fflush 函数(stdin,stdout)

发布时间:2019-06-23 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了关于 fflush 函数(stdin,stdout)脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

写在最前面

别人的程序里看到这个函数,本着学习的态度整理一番。

p.s. 新添加一些内容没,我从 关于fflush(stdin)清空输入缓存流(C/C++) 新手必看!!这里看来的,对理解缓冲区有很大帮助。

fflush(stdout)

PRintf()后使用fflush(stdout)的作用是立刻将要输出的内容输出。
当使用printf()函数后,系统将内容存入输出缓冲区,等到时间片轮转到系统的输出程序时,将其输出。
使用fflush(out)后,立刻清空输出缓冲区,并把缓冲区内容输出。
例如:

for (ctr = 1; ctr <= wait; ctr++)
{
printf("."); /* print a dot */
fflush(stdout); /* force dot to print on buffered machines */
sleep((int) 1); /* pause 1 second */
}

用fflush(stdout)能使机器每输出一个.暂停一秒钟,而不会出现乱序(例如:PP。。。PP。PPP。。。等)现象。

一个经典的例子:



#include <stdio.h>  
int main()  
{  
    char c;  
    scanf("%c", &c);  
    printf("%dn", c);  
  
    //fflush(stdin); // 冲掉“马桶”中的无用值  
    
    scanf("%c", &c);  
    printf("%dn", c);  
      
    return 0;  
  
}  

如果输入1后回车,输出的是49和10,很正常,因为回车就是在ASCii中就是49。

fflush(stdin)

功能:清空输入缓冲区,通常是为了确保不影响后面的数据读取(例如在读完一个字符串后紧接着又要读取一个字符,此时应该先执行fflush(stdin);)。

  • 这里给大家提个醒,为什么用fflush(stdin)是错的?

先看下下面的程序

#include <stdio.h>
int main( void )
{
int i;

for (;;)
   {
      fputs("Please input an integer: ", stdout);
      scanf("%d", &i);
      printf("%dn", 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) 也没什么大问题。

  • 那么为了移植性以及程序的鲁棒性,我们应该怎么做?

清空输入缓冲区的方法

   /* 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 ) ;    /*可直接将这句代码当成fflush(stdio)的替代,直接运行可清除输入缓存流*/
        /* 使用 scanf("%*[^n]"); 也可以清空输入流, */
        /* 不过会残留 n 字符。                          */

        printf("%dn", i);
     }

     return 0;
   }
   
  

上面是c版本的,下面是c++版本的。

  
  
  
/* 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;
   } 
  
  

个人觉得这两个版本写的不错,可以添加到自己的私有库里。根据这个原理自己还可以改写一些别的版本。

总结

c99对这个函数的定义:

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

这个函数还是很有用的,可以加深对缓存的理解。没有想到一个输入都有这么多需要关注的东西,真的是c++是学一辈子的东西!-_-

脚本宝典总结

以上是脚本宝典为你收集整理的关于 fflush 函数(stdin,stdout)全部内容,希望文章能够帮你解决关于 fflush 函数(stdin,stdout)所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。