1

我正在(重新)学习编程,我从 C 开始。我的 IDE(如果我可以这么说的话)是 Windows7 上的 cygwin(32 位)和 Visual-Studio 2010。我总是使用 gcc (cygwin) 以及 VS2010 编译器编译我编写的代码。我想,我这样做是因为我认为这是一种很好的学习方式。无论如何,我刚刚了解了 fflush(stdin),即刷新标准输入缓冲区。似乎是一个很好的功能,因为否则,使用 scanf 似乎很痛苦。所以我根据我教科书中的一个例子编写了下面的代码。它既可以用 cygwin 中的 gcc 编译,也可以用 VS2010 编译。当我运行 VS 编译程序时它工作正常(s.below),当我在 cygwin 中运行 gcc 编译程序时,fflush(stdin)不会刷新 stdin 缓冲区(s.below)。我已经阅读了一些关于 fflush(stdin) 在某些情况下具有未定义行为的线程。不管这可能意味着什么,我从 C for Linux Programming 教科书中摘录了它。如果 fflush(stdin) 不是清除标准输入缓冲区中内容的有效方法,还有什么其他标准方法?

非常感谢任何答案!

==程序在Windows下运行:

enter a long integer and a double
23.00 78.99
lint = 23
dt = 0.00

enter a five digits input
78493
u entered 78 and 493

==程序在 Cygwin 中运行:

enter a long integer and a double
23.00 78.99
lint = 23
dt = 0.00

enter a five digits input
u entered 78 and 2665720

==代码====

long lint;
double dt;
int fp, sp;
char fn[50], ln[50];

/* using the l modifier to enter long integers and doubles */
puts ("enter a long integer and a double");
scanf("%ld %lf", &lint, &dt);

printf("lint = %d\ndt = %.2f\n", lint, dt);

fflush(stdin); /*DOES NOT WORK UNDER CYGWIN!?*/

/* use field width to split input */

puts("\nenter a five digits input");
scanf("%2d %3d", &fp, &sp);

printf("u entered %d and %d\n", fp, sp);
4

4 回答 4

2

C11 在 7.21.5.2.2 说(强调我的):

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

这意味着您不应该调用fflush输入流(除非您正在为非常特定的操作系统和定义了行为的库编写代码)

这是有充分理由的!您通常会认为这fflush(stdin)会刷新您刚刚输入的行,对吗?好吧,还有更多。想象一下像这样运行你的程序:

$ ./program < input_file

在这种情况下,理论上所有文件都已经在stdin. 因此,刷新该缓冲区等于结束您的输入,这是一个非常无用的操作。由于这些原因,fflush不能对输入流有非常明智的行为,这就是为什么它在它们上未定义的原因。


如果你想忽略当前行,有更好的方法来做到这一点。一个例子如下:

void flush_line(FILE *fin)
{
    int c;
    do
    {
        c = fgetc(fin);
    } while (c != '\n' && c != EOF);
}

这会逐个字符地读取输入并停止,直到出现文件结尾、读取错误或行尾。

于 2013-11-19T20:19:49.647 回答
2

在标准中,没有为输入流定义 fflush()。在Microsoft 的文档中,它是明确定义的。

结果是,虽然您可以将它与具有明确定义行为的 Microsoft 的 C 库一起使用,但这种行为是不可移植的。

如果您想使用 GCC 并进行这项工作,那么您可以使用 MinGW/GCC,因为它使用 Microsoft 的 C 运行时而不是 glibc。

于 2013-11-19T20:46:42.957 回答
1

您不应该刷新输入流。您观察到的差异来自此操作的行为未定义这一事实。

于 2013-11-19T20:13:50.070 回答
0

据我了解,你正在为 Linux 编写这个程序,不管你信不信,它fflush(stdin)只能在 Windows 下运行。(这至少是我从名为 C for dummies 的 C 书籍中得到的)。fflush(stdin)Linux 上的替代方案是fpurge(stdin). 试试看它是否适合你。

于 2017-06-25T21:26:19.393 回答