【问题标题】:Going back to normal terminal I/O after closing ncurses window关闭 ncurses 窗口后返回正常的终端 I/O
【发布时间】:2014-12-11 22:45:56
【问题描述】:

在我制作的游戏中,我使用 initscr() 创建了一个 ncurses 窗口,然后用户玩游戏,当游戏结束时,程序使用 endwin() 关闭窗口,然后打印一些语句并使用用户获取输入分别是 printf 和 scanf。我的问题是,每当游戏结束时,scanf 总是在 printf 之前执行。所以它等待响应,一旦用户输入响应,它就会打印 scanf 语句之前和之后的所有内容。下面是一些示例代码:

...

endwin();
system("clear"); /* Clears terminal window */
printf("New high score!\nPlease enter your first name: ");
scanf("%s",name);

... /* file I/O stuff */

printf("Congratulations, %s!",name);

如您所见,printf 语句在 scanf 语句之前,但由于某种原因 scanf 先执行。我在没有 ncurses 窗口的情况下测试了代码,得到了想要的结果。有谁知道是什么原因造成的?

【问题讨论】:

  • 您需要在您的printf() 调用之后fflush(stdout);,或者用换行符终止格式字符串。与诅咒无关。
  • @PaulGriffiths 好的,这行得通,但为什么我必须打电话给fflush(stdout) 才能让scanf() 重新开始工作?从我收集的内容来看,它基本上会强制所有输出流进行更新,但是在使用 printf()/scanf() 时我通常不需要它(或者我会吗?)
  • 你不需要 - 你调用它是为了让 printf() 在你的 scanf() 调用开始之前实际写入屏幕。
  • @PaulGriffiths 谢谢,我想我现在明白了。

标签: c unix io ncurses curses


【解决方案1】:

与诅咒无关。

这个陈述显然是错误的,因为使用 curses 会产生影响,正如问题所述:

如您所见,printf 语句在 scanf 语句之前,但 出于某种原因 scanf 首先执行。我测试了没有 ncurses 窗口,我得到了想要的结果。有谁知道是什么 造成这种情况?

虽然fflush(stdout) 给出了期望的结果是正确的,但这并不能回答问题。

造成这种情况的原因可能是实现定义的标准 I/O 特性在请求输入时刷新 缓冲的行 stdout(有时记录在 man setbuf 中),以及 cursesstdout 设置为完全缓冲,从而禁用自动刷新。

【讨论】:

    【解决方案2】:

    您可以在讨论NCURSES_NO_SETBUF的手册页中阅读:

    • 为了获得良好的性能,大多数 curses 实现将输出缓冲从面向行更改为面向缓冲区(以便库可以进行更大、更高效的写入)
    • 因为这意味着对标准输出的所有 写入都会被缓冲,这很麻烦。 ncurses 提供了一个选项(环境变量)来覆盖缓冲。
    • 2012 中发生了变化,通过完全消除 stdout 缓冲来解决信号处理问题。
    • 但是,“消除”缓冲意味着 ncurses 使用自己的缓冲区。它会在endwin 中刷新那个,但在切换到/从curses 模式时不会刷新stdout
    • 少数应用程序需要修改才能刷新标准输出。

    2012 年对 ncurses 的更改是 August 2015 中 ncurses6 版本的一部分。 OP 的问题是关于 ncurses5.9(或更早版本),因为它描述了一个标准输出被缓冲的应用程序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-26
      • 2021-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-22
      相关资源
      最近更新 更多