终端中运行的某些应用程序可以删除其输出。例如 当它告诉你等待时,它会显示一系列在不同长度之间交替的点。
如何在C中实现终端中的擦除输出?是通过反向换行完成的吗?
程序是否只能删除当前行中的前一个字符,而不是stdout中前一行中的字符?
感谢。
答案 0 :(得分:3)
取决于终端。
Windows上的COMSPEC shell(通常称为DOS提示符或command.com)在C中公开API以控制游标。我还没有完成任何Windows编程,所以我无法告诉你很多。
大多数其他终端(特别是在unixen上)模拟类似于VT100串行终端的协议(VT100终端是物理设备,监视器和键盘,您连接到调制解调器或串行端口以与服务器通信)。 / p>
在VT100终端上,回车和换行是单独的命令,都是一个字节。回车命令将光标设置为行的开头。换行命令将光标向下移动一行(但不能将光标自身带到行的开头)。 unixen上的大多数shell会在换行后自动插入回车符,但在回车后几乎不会插入换行符。
有了这些知识,最简单的实现就是简单地输出一个回车并重新打印整行:
printf("\rprogress: %d percent ", x);
请注意该行末尾的额外空格。打印"\r"
不会删除该行,因此在旧行上重新打印可能会在屏幕上留下一些旧字符串。额外的空格用于尝试和擦除旧行的其余部分。
如果您使用Google搜索"VT100 escape secquence",您将找到允许您执行操作的命令,例如删除当前行,更改文本颜色,转到屏幕上的特定行/列等。最受欢迎使用VT100序列是输出彩色文本。但你也可以用它们做其他事情。
下一个最简单的实现是干净地删除该行并重新打印它:
printf("\033[2K\rprogress: %d percent", x);
\033[2K
是删除当前行的转义序列(ESC [2K)。
如果您愿意,可以从这里获得更多创意。您可以使用cursor save / restore命令和erase to line of line命令仅擦除要更新的部分(而不是整行)。您可以使用goto命令将光标放在屏幕上的特定位置以更新文本等。
应该注意的是,更先进的东西,如VT102序列或一些完整的ANSI转义序列,通常不能在终端上移动(通过终端我不是指shell,我的意思是终端:rxvt, xterm,linux终端,超级终端(在windows上)等。
如果你想要可移植性(和/或理智的API),你应该使用curses或ncurses库。
如果你想知道它是如何完成的,那么它是如何完成的。它只是将特殊格式的字符串打印到屏幕上(COMSPEC shell除外)。有点像HTML但是老派。