如果您的终端(或者更可能是终端模拟器)支持VT100风格的转义序列,您可以打印特定的代码序列来控制光标位置、清除部分或全部屏幕/窗口等。
例如,要将光标向上移动1行:
printf("\x1b[A");
fflush(stdout);
要将光标向上移动两行,可以重复这个动作两次,或者:
printf("\x1b[2A"});
fflush(stdout);
这些通常被称为
ANSI转义码; 链接指向一个维基百科文章,列出了许多这样的代码。它们最初是由旧的DEC VT-100终端实现的,大多数现代终端和仿真器都模拟该终端。
还有这段文字:
printf("\x1b[J");
fflush(stdout);
将清除屏幕的一部分,从当前光标位置到底部。
这些序列应该足以满足您的需求。(它们可能在Windows命令窗口中无法工作。)
更加便携的方法是,如果您的系统支持,可以使用termcap
或terminfo
来确定当前终端的正确命令序列(由$TERM
环境变量确定)。tput
命令可让您在命令行上执行此操作;有关更多信息,请参阅man tput
。实际上,您现在很难找到不支持VT100兼容终端的支持termcap或terminfo的系统;打印原始转义序列严格来说并不是可移植的,但可能已经足够了。
建议:您的程序应该具有禁止任何此类控制序列的选项;例如,如果用户想要将输出重定向到文件,则不希望在文件中包含这些转义序列。一些程序仅在它们能够确定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;
}