首页 > 解决方案 > 如何在短宽终端中正确实现不断刷新的进度条?

问题描述

我必须在终端上写一个自刷新进度条——它表示到目前为止已经复制了多少文件。我倾向于每 1000 个字节左右刷新一次输出。为了刷新屏幕,我使用了以下大纲:

printf("\r"); // clear previous output

// output is the progress bar, percent is an integer (0 to 100)
printf("%s %d file written", output, percent);

当终端很大时它工作正常。但是,当终端很小,以至于整个进度条都无法放入其中时,回车不起作用。它只清除视觉单行,而不是整行。我写了一个示例程序来演示:

printf(
    "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij"
    "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghi"
    "j");
printf("\rCHECK");

如下图所示,由于终端很小,所以只删除了整个打印输出的一部分。

在此处输入图像描述

放置多个回车无效。

那么,用 C 语言构建这样一个不断刷新的终端输出有什么好的方法呢?

我也尝试过清除屏幕(printf("\033[2J");),但它对我不起作用。它倾向于在输出的开头插入任意数量的空格,例如:

在此处输入图像描述

标签: cterminalcarriage-return

解决方案


通常,判断您的消息是否已换行到终端的下一行的唯一方法是将其与终端宽度(列数)进行比较。您可以使用 terminfo(3) 获取该信息

#include <term.h>

int main() {
    setupterm(0, 1, 0);  /* default terminal setup from the TERM envvar */

现在您可以访问全局变量columns以了解终端上有多少列。您也可以使用putp(tigetstr("cuu1"));在终端上上一行。因此,您可以跟踪您的状态消息有多长,并计算出您需要走多远才能回到它的开头。


推荐阅读