3

愚蠢的问题但是,是否可以使用 printf(); 在没有换行的情况下在标准输出上换行?如果没有,如果可能的话,关于如何覆盖 2 行以上的任何提示?

我正在尝试生成一种进度条,但在多行上。有任何想法吗?

编辑:所以是的,我接受了以下答案,尽管它不适用于我的具体情况。我正在尝试覆盖 2+ 行而不是单行。

printf("12345\r");
fflush(stdout);
printf("67890\n");

结果是
$ ./a.out
67890

但我想要实现的是用新数据覆盖 2+ 行。类似于进度条,但在 2+ 行上,除了我有一些数据的百分比数字。

4

2 回答 2

3

要重写一行的全部(或部分),您需要使用正确数量的退格字符。例如:

printf("some text");
printf("\b\b\b\bstuff");

将输出:

some stuff

这对于简单的东西很好;对于更复杂的事情,您应该使用ncurses,它使用 ANSI 转义技巧来操纵屏幕周围的光标。

于 2013-03-06T15:46:43.007 回答
2

如果您的终端(或者更可能是终端仿真器)支持 VT100 样式的转义序列,您可以打印特定的代码序列来控制光标位置、清除部分或全部屏幕/窗口等。

例如,要将光标向上移动 1 行:

printf("\x1b[A");
fflush(stdout);

要将光标向上移动 2 行,请执行两次或:

printf("\x1b[2A"});
fflush(stdout);

这些通常称为ANSI 转义码;该链接指向列出其中许多的 Wikipedia 文章。它们首先由旧的 DEC VT-100 终端实现,大多数现代终端和仿真器都对其进行了仿真。

还有这个:

printf("\x1b[J");
fflush(stdout);

将清除部分屏幕,从当前光标位置到底部。

这些序列应该足以满足您的需求。(它们可能无法在 Windows 命令窗口中工作。)

更便携,如果您的系统支持它,您可以使用termcapterminfo确定当前终端的正确命令序列(由$TERM环境变量确定)。该tput命令允许您在命令行上执行此操作;man tput了解更多信息。实际上,您现在不太可能找到一个支持 termcap 或 terminfo 的系统,其终端与 VT100 不兼容;打印原始转义序列严格来说是不可移植的,但可能已经足够好了。

一个建议:您的程序可能应该有一个选项来禁止任何此类控制序列;例如,如果想要将输出重定向到文件的用户不希望在文件中包含这些转义序列。有些程序只有在可以确定 stdout 是终端时才使用控制序列,但显式选项也是一个好主意。

*更新:*

这是我编写的一个程序,它演示了如何使用terminfo. 它应该适用于几乎任何类 Unix 系统。

#include <stdio.h>
#include <stdlib.h>
#include <curses.h>
#include <term.h>
#include <unistd.h>

int main(void) {
    const char *term = getenv("TERM");
    if (term == NULL) {
        fprintf(stderr, "TERM environment variable is not set\n");
        exit(EXIT_FAILURE);
    }
    setterm(term);
    for (int i = 0; i < 10; i ++) {
        putp(tparm(clr_eos));
        printf("%d\n%d\n", i, i+1);
        sleep(1);
        putp(tparm(parm_up_cursor, 2));
    }
    return 0;
}
于 2013-03-06T16:26:23.577 回答