fflush(stdin)在C编程中做了什么?
我是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 );
答案是fflush(stream)
只是为输出流正式定义,因此fflush(stdout)
是正常的,但fflush(stdin)
不是。
fflush(stream)
的目的是使操作系统将任何缓冲区刷新到底层文件。 对于合法使用的示例,学生经常遇到“我的提示没有出现!”等问题,如果他们做了类似的事情:
printf("Enter a number: ");
但是,他们发现这很好用:
printf("Enter a number:\n");
当然,他们在提示后不需要换行,所以他们有一点问题。
这样做的原因是操作系统缓冲了对stdout
的输出,并且(通常)默认行为只是在遇到换行符时实际将输出写入终端。 在printf()
之后添加fflush(stdout)
printf()
解决了问题:
printf("Enter a number: "); fflush(stdout);
现在,通过类比工作,人们常常认为fflush(stdin)
应该丢弃任何未使用的输入,但是如果你想一点就没有多大意义。 “刷新”输入缓冲区意味着什么? 它在哪里被“冲” 到 ? 如果刷新输出缓冲区,输出将被发送到底层文件或终端,最终它会最终结束,但输入 “最终会最终结束”? 没有办法知道! 如果输入流数据来自文件或管道或套接字,那么行为应该是什么? 输入流根本不清楚fflush()
的行为应该是什么,但在所有情况下输出流都非常清楚。 因此, fflush()
仅为输出流定义。
错误使用fflush(stdin)
变得司空见惯的原因在于,许多年前,一些操作系统确实实现了一种方案,它可以像许多人预期的那样工作,丢弃未使用的输入。 Microsoft DOS就是一个很好的例子。 令人惊讶的是, Linux的现代版本还为输入流实现了fflush()
。
使用“额外”不需要的终端输入做正确的事情就是阅读它并且不做任何事情。 这几乎就像调用fflush(stdin)
一样简单,无处不在,并且不依赖于正式的未定义行为。
C标准说:
如果流指向输入流或未输入最近操作的更新流,则fflush函数会将该流的任何未写入数据传送到主机环境以写入该文件; 否则,行为未定义 。
POSIX说 (也明确遵循C标准):
如果流指向输入流或未输入最近操作的更新流,则fflush()将导致该流的任何未写入数据写入文件,…
但Linux手册页说:
对于输出流,fflush()强制通过流的底层写入函数写入给定输出或更新流的所有用户空间缓冲数据。 对于输入流,fflush()会丢弃从底层文件中提取但尚未被应用程序使用的任何缓冲数据 。 流的打开状态不受影响。
fflush(stdin)
调用未定义的行为。
fflush()
仅为输出流定义。 你不应该这样做。
在Unix上,Ctrl-Z发送TSTP信号(SIGTSTP),默认情况下会导致进程暂停执行。