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

C g*_*ics 19 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 );
Run Code Online (Sandbox Code Playgroud)

Emm*_*met 32

对此的答案fflush(stream)是仅对输出流进行了正式定义,因此fflush(stdout)可以,但fflush(stdin)不是.

目的fflush(stream)是使操作系统将任何缓冲区刷新到底层文件.对于合法使用的示例,学生经常遇到类似"我的提示没有出现!"的问题,如果他们这样做:

printf("Enter a number: ");
Run Code Online (Sandbox Code Playgroud)

但是,他们发现这很好用:

printf("Enter a number:\n");
Run Code Online (Sandbox Code Playgroud)

当然,他们在提示后不需要换行,所以他们有一点问题.

这样做的原因是输出到stdoutOS由OS缓冲,并且(通常)默认行为仅在遇到换行时实际将输出写入终端.添加fflush(stdout)printf()解决问题:

printf("Enter a number: ");
fflush(stdout);
Run Code Online (Sandbox Code Playgroud)

现在,通过类比工作,人们常常认为fflush(stdin)应该丢弃任何未使用的输入,但如果你想一点就没那么有意义了."刷新"输入缓冲区意味着什么?它在哪里被"冲" ?如果刷新输出缓冲区,输出将被发送到底层文件或终端,无论如何它最终都会结束,但输入 "最终会最终结束"?没有办法知道!如果输入流数据来自文件或管道或套接字,那么行为应该是什么?这不是在所有的输入流的行为有什么明确的fflush()是应该的,但它是在所有情况下的输出流很清楚.因此,fflush()仅为输出流定义.

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

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

Ç标准说:

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

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

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

Linux手册页说:

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

  • 可能有用的是要注意这一点(Linux为其他未定义的行为提供定义)是特定于实现的扩展,对于对可移植代码感兴趣的人应该避免使用. (4认同)

chr*_*hrk 16

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

fflush()仅为输出流定义.你不应该这样做.


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