fflush(stdin)在C编程中做了什么?

时间:2014-04-07 00:45:35

标签: c operating-system signals

我是C编程的新手,我正在努力了解fflush(stdin)的确如何运作。

在下面的例子中,fflush(stdin)清除所有缓冲区,还是清除第三项后输入的内容?我的意思是用户输入帐号,空格,名称,空格,余额。这是真的,从这一点开始,用户输入的内容将被fflush(stdin)刷新吗?并且stdin不会是空的。

为什么我这样说是因为它进入了一个while循环并开始写入文本文件。

我的第二个问题是Ctrl-Z是否会告诉操作系统停止要求用户输入输入?

printf( "Enter the account name and balance. (separated by spaces)\n" );
  printf( "Enter EOF to end input. (Ctrl-Z)\n" );
  printf( "? " );
  scanf( "%d%s%lf", &account, name, &balance );
  fflush(stdin);

  // write account, name and balance into file with fprintf
  while ( !feof( stdin ) )
  { 
     //fflush(stdin);
     fprintf( cfPtr, "%d %s %.2f\n", account, name, balance );
     printf( "? " );
     scanf( "%d%s%lf", &account, name, &balance );
  }

  fclose( cfPtr );

2 个答案:

答案 0 :(得分:32)

答案是fflush(stream)仅为输出流正式定义,因此fflush(stdout)可以,但fflush(stdin)不是。

fflush(stream)的目的是使操作系统将任何缓冲区刷新到底层文件。对于合法用途的例子,学生经常遇到“我的提示不会出现!”等问题,如果他们这样做:

printf("Enter a number: ");

然而,他们发现这很好用:

printf("Enter a number:\n");

当然,他们在提示后不想换行,所以他们有点问题。

原因是操作系统缓存了stdout的输出,并且(通常)默认行为只是在遇到换行符时实际将输出写入终端。在fflush(stdout)解决问题后添加printf()

printf("Enter a number: ");
fflush(stdout);

现在,通过类比工作,人们常常认为fflush(stdin)应该丢弃任何未使用的输入,但是如果你仔细考虑一下并没有多大意义。 “刷新”输入缓冲区意味着什么?它在哪里“刷新”?如果刷新输出缓冲区,输出将被发送到底层文件或终端,最终它会最终结束,但输入“最终会在哪里结束”?没有办法知道!如果输入流数据来自文件或管道或套接字,那么行为应该是什么?对于输入流而言, 因此,fflush()仅为输出流定义。

错误使用fflush()变得司空见惯的原因在于,许多年前,一些操作系统已经实施了一个方案,它可以像许多人预期的那样工作,丢弃未使用的输入。 Microsoft DOS 就是一个很好的例子。令人惊讶的是,现代版本的 Linux 还为输入流实现了​​fflush(stdin)

使用“额外”不需要的终端输入做的正确的事情就是阅读它并且不做任何事情。这几乎就像调用fflush()一样简单,无处不在,并且不依赖于正式的未定义行为。

C 标准说:

  

如果流指向输出流或未输入最新操作的更新流,则fflush函数会将该流的任何未写入数据传递到主机环境写入文件; 否则,行为未定义

POSIX says(也明确遵循 C 标准):

  

如果流指向输出流或未输入最新操作的更新流,fflush()将导致该流的任何未写入数据写入文件。 ..

但是Linux manpage说:

  

对于输出流,fflush()强制通过流的底层写入函数写入给定输出或更新流的所有用户空间缓冲数据。 对于输入流,fflush()会丢弃从底层文件中提取但尚未被应用程序使用的任何缓冲数据。流的开放状态不受影响。

答案 1 :(得分:16)

fflush(stdin)调用未定义的行为。

仅为输出流定义

fflush()。你不应该这样做。


在Unix上,Ctrl-Z发送TSTP信号(SIGTSTP),默认情况下会导致进程暂停执行。