printf没有在控制台上输出

44

我正在学习C语言。我使用Eclipse(juno)作为我的IDE,并安装了CDT插件。我还解压了mingw64(GCC编译器)。我编写了一个非常简单的程序来查看它是否正常工作。这是我的代码:

#include <stdio.h>

int main()
{
    int age;
    printf("Hello, please enter your age:\n");
    scanf("%d", &age);
    printf("Your age is %d", age);
    return 0;
}

问题在于输出缓冲区被填充了第一个printf的字符串值,但并没有将其输出到控制台。我必须输入一个数字,然后缓冲区才会将所有数据倾倒到控制台,因此我看到控制台上的内容类似于这样:

1
Hello, please enter your age:
Your age is 1

与预期的不同:

Hello, please enter your age:
1
Your age is 1
现在,我发现在第一个printf后面可以使用fflush(stdout),但我认为这种解决方案既不优雅也不必要。你们有什么想法可以帮我解决这个问题吗?
编辑 - 因为我正在学习这个课程,所以不能使用课程之外的任何东西,所以我只能使用printfscanf
新编辑 - 我想我已经找到了一个解释。正如我所说,我正在输出到Eclipse中的控制台视图。奇怪的是,如果我从Windows的命令行编译和运行程序,我得到了想要的结果。因此,我认为eclipse实际上是将输出写入文件并在控制台窗口中显示。如何强制eclipse在我的运行配置中打开一个真正的命令行窗口?

4
顺便提一下,使用 fflush() 函数是没有问题的,它们非常方便。 - Mike
1
这是非常奇怪的行为,\n 应该刷新 stdout - KevinDTimm
1
这不是一个重复的问题,因为我不能使用 fflushfprintf 函数。当我在 Windows 命令行中运行 gcc 时,可以得到正确的结果,所以我怀疑是错误的 Eclipse 配置。有哪些配置需要注意吗? - Mr T.
非常赞赏您承认这是为了课程而提出的问题。“替我做作业”这种行为是不被看好的,但像这样真正有针对性的问题则是非常棒的,因为这也是完成作业的目的(学习手头的知识)。 - Randall
7个回答

39

输出被缓冲了。

默认情况下,stdout是按行缓冲的,这意味着'\n'应该会刷新缓冲区。为什么在你的情况下没有发生呢?我不知道。我需要更多关于你的应用程序/环境的信息。

但是,你可以使用setvbuf()来控制缓冲。

setvbuf(stdout, NULL, _IOLBF, 0);

这将强制使标准输出按行缓冲。

setvbuf(stdout, NULL, _IONBF, 0);

这将强制stdout无缓冲,因此您不需要使用fflush()。 请注意,如果有大量的打印输出,则会严重影响应用程序性能。


我尝试了这个解决方案并发现在调试模式下不能单步执行printf。它被卡住了,我得到了:“*stopped,reason =”end-stepping-range",frame = ...” 的错误消息。 - yehudahs
这对我来说是解决方案。如果我直接在终端窗口中运行程序,我可以看到输出,但是如果我尝试使用tee甚至将终端输出写入文件,我将什么也得不到。 - Chris Watts
你说得对。在我的情况下,输出被缓存,并在程序结束后卸载,写入在执行过程中积累的所有缓冲字符串,紧接着程序结束之后。 - another

23

显然这是Eclipse的一个已知缺陷。该缺陷已通过WONT-FIX解决。但我不知道为什么会这样。这是链接: Eclipse C控制台缺陷


2
仍未解决。必须在您的代码中禁用缓冲或以其他方式处理它。 - Hack-R
这与Clion相同。 - moshevi

9
你可以尝试将内容写入stderr,而不是stdout。
fprintf(stderr, "Hello, please enter your age\n");

您还应该查看相关主题。

(注:内容已经翻译,保留了HTML标记,请核对是否符合格式要求。)

我正在大学学习C语言课程,因为这是一门101级别的课程,所以我不能使用不在教材中的东西(目前只能使用printf和scanf)。出于同样的原因,我也不能使用fflush。 - Mr T.
你是输出到某种控制台吗?我在Linux上工作...所以我完全不熟悉Windows的编译过程等等。 - Kitchi
我所说的控制台是Eclipse IDE中的控制台视图。但正如我在另一条评论中所说,当我使用gcc通过命令行编译时,我得到了想要的结果,因此我强烈怀疑这是一个Eclipse配置问题。有什么想法吗? - Mr T.
2
有时候如果编译器认为输出的是文件而不是控制台,即使在换行符时也不会立即清空缓冲区,直到它完全满了。也许这就是发生的情况,因为你通过gcc得到了想要的结果。 - Kitchi
没错 - 那么是否有可能强制Eclipse在Windows命令行中运行C程序,而不是在Eclipse的控制台视图中运行? - Mr T.
就像我说的,我对Eclipse完全不熟悉。但是这个链接可能对你的问题有用。 - Kitchi

9

在打印之前尝试设置这个:

setvbuf (stdout, NULL, _IONBF, 0);

是的 - 这个方法可行,并且在我在正确答案中发布的链接中也有建议。 - Mr T.

5
正如其他人所指出的,输出可以在程序内部进行缓冲,然后控制台或shell才有机会看到它。
在类Unix系统中(包括mac),stdout默认具有基于行的缓冲。这意味着只要程序看到一个换行符,它就会清空其stdout缓冲区。
但是,在Windows上,换行符不再是特殊字符,因此使用完全缓冲。Windows根本不支持行缓冲;请参见msdn页面上的setvbuf
因此,在Windows上,一个好的方法是完全关闭stdout缓冲,如下所示:
setvbuf (stdout, NULL, _IONBF, 0);

1
  1. 在你的项目文件夹中创建一个名为“.gdbinit”的文本文件。它将包含你的gdb调试器配置。
  2. 编辑“.gdbinit”,并添加以下行(不要包括引号):“set new-console on”
  3. 在构建项目后,在项目上右键单击“Debug”>“调试配置”,如下所示: Debug configuration

  4. 在“调试器”选项卡中,确保“GDB命令文件”现在指向你的“.gdbinit”文件。否则,请输入你的“.gdbinit”配置文件的路径: Gdb configuration

  5. 单击“应用”和“调试”。应该会启动本地DOS命令行,如下所示: Console


有人测试过这个吗? - Danijel

1
c:\gygwin\bin 添加到 PATH 环境变量中,可以作为系统环境变量或在您的 Eclipse 项目中进行设置(属性-> 运行/调试-> 编辑)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接