愚蠢的问题,但是, 是否可以使用printf()在没有换行符的情况下在stdout上打破一行;?如果不是,如果可能的话,有关如何覆盖2+行的任何提示?
我试图在多行上生成一种进度条。 有什么想法吗?
编辑: 所以我接受了下面的回答,虽然它不适用于我的具体案例。 我试图覆盖2 +行 而不是一行。
printf("12345\r");
fflush(stdout);
printf("67890\n");
结果为$ $ ./a.out
67890
但我想要实现的目标是用新数据覆盖2行以上。 类似于进度条,但是在2行以上,除了我有一些数据的百分比数。
答案 0 :(得分:3)
要重写行的所有(或部分),您需要使用正确数量的退格符。例如:
printf("some text");
printf("\b\b\b\bstuff");
将输出:
some stuff
这对于简单的东西来说很好;对于更复杂的东西,你应该使用ncurses,它使用ANSI-escape聪明来操纵屏幕周围的光标。
答案 1 :(得分:2)
如果您的终端(或更可能是终端仿真器)支持VT100样式的转义序列,您可以打印特定的代码序列来控制光标位置,清除部分或全部屏幕/窗口等。
例如,将光标向上移动1行:
printf("\x1b[A");
fflush(stdout);
要将光标向上移动2行,请执行两次或:
printf("\x1b[2A"});
fflush(stdout);
这些通常被称为ANSI escape codes;该链接指向列出其中许多内容的维基百科文章。它们首先由旧的DEC VT-100终端实现,该终端由大多数现代终端和仿真器模拟。
而且:
printf("\x1b[J");
fflush(stdout);
将清除部分屏幕,从当前光标位置到底部。
这些序列应足以满足您的需求。 (它们可能无法在Windows命令窗口中运行。)
更便携,如果您的系统支持它,您可以使用termcap
或terminfo
来确定当前终端的正确命令序列(由$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;
}