使用 ncurses 后的 printf()/puts()

sev*_*vko 5 c ncurses

我在 C 项目中使用该库,在初始化取消初始化curses 后ncurses遇到了使用printf()/的问题。这是一个简化的说明:puts()

initscr();
endwin();

puts("first");
usleep(1e6);
puts("second");
Run Code Online (Sandbox Code Playgroud)

firstsecond当包含的可执行文件退出后(一秒多一点后), 和 才会出现在屏幕上,而不是先打印,first然后在一秒后打印second. ncurses似乎以stdout某种方式缓冲并且仅在退出时刷新它。fflush(stdout)似乎解决了问题:

initscr();
endwin();

puts("First.");
fflush(stdout);
usleep(1e6);
puts("Second");
Run Code Online (Sandbox Code Playgroud)

stdout手动刷新时,输出将按预期显示(带有第二个间隙)。puts()不过,如果我之后要usleep()在中间添加更多语句,我需要在每个语句之后重复调用fflush(stdout),并且我想知道是否有更好的解决方案,例如将程序永久重置为预诅咒模式。

nma*_*ier 4

ncurses调用setvbuf,将流置于全缓冲模式。要么指定环境变量NCURSES_NO_SETBUF来指示它不更改缓冲,要么通过setvbuf再次调用来恢复缓冲模式,尽管man 3 setvbuf建议不要这样做:

setvbuf() 函数可以随时使用,但如果流处于“活动”状态,则可能会产生特殊的副作用(例如丢弃输入或刷新输出)。便携式应用程序应该在任何给定的流上仅在执行任何 I/O 之前调用它一次。

以下是如何恢复stdout行缓冲和stderr再次无缓冲:

#include <stdio.h>
#include <unistd.h>
#include <ncurses.h>

int main() {
  initscr();
  endwin();

  setvbuf(stdout, NULL, _IOLBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);

  puts("First.");
  usleep(1e6);
  puts("Second");
  return 0;
}
Run Code Online (Sandbox Code Playgroud)