首页 > 解决方案 > 为什么 termcaps 在 `write` 系统调用之前不起作用?

问题描述

为什么这个程序的输出没有下划线

int main() {
  tgetent(NULL, getenv("TERM"));
  tputs(tgetstr("us", NULL), 1, &putchar);
  write(1, "Hello world!\n", 13);
  tputs(tgetstr("ue", NULL), 1, &putchar);
}

但这

int main() {
  tgetent(NULL, getenv("TERM"));
  tputs(tgetstr("us", NULL), 1, &putchar);
  puts("Hello world!");
  tputs(tgetstr("ue", NULL), 1, &putchar);
}

编辑

事实上,问题在于缓冲区管理!如果我添加fflush,则字符串会正确加下划线

int main() {
  tgetent(NULL, getenv("TERM"));
  tputs(tgetstr("us", NULL), 1, &putchar);
  fflush(stdout);
  write(1, "Hello world!\n", 13);
  tputs(tgetstr("ue", NULL), 1, &putchar);
}

标签: cunixterminaltermcap

解决方案


差异的原因是putcharandputs缓冲的,而write不是。在这个例子中

int main() {
  tgetent(NULL, getenv("TERM"));
  tputs(tgetstr("us", NULL), 1, &putchar);
  write(1, "Hello world!\n", 13);
  tputs(tgetstr("ue", NULL), 1, &putchar);
}

写的字符

write(1, "Hello world!\n", 13);

可能首先到达屏幕,因为(与tputs调用不同)它们是立即写入的。调用写入的字符tputs存储在缓冲区中(通常比从返回的字符串大得多tgetstr,并且由于您没有提供其他方法来刷新缓冲区,因此这些字符由运行时的清理在退出时写入。

如果没有显式的 return 语句,C 标准保证它与调用具有相同的效果exitfflush对每个打开的文件执行 an ——包括诸如stdout之类的流)。

虽然您原则上可以构造一个具有极长字符串的 termcap,但 termcap 描述应该限制为 1023 个字节(甚至 terminfo 描述通常限制为 4096 个字节),而标准 I/O 缓冲区大小通常是该大小的几倍限制,所以如果没有大量工作(即更改运行时......),您将不会看到这些tputs调用被写出来。


推荐阅读