如何在C中擦除当前打印的控制台行?我正在Linux系统上工作。例如 -
printf("hello");
printf("bye");
我想在同一行上打印再见,代替您好。
Answers:
您可以使用VT100转义码。包括xterm在内的大多数终端都支持VT100。要擦除线,此为^[[2K
。在C中,它给出:
printf("%c[2K", 27);
\r
仍然需要。请注意,%c
不必使用。另类:printf("\33[2K\r");
printf("\r ");
。
一些有价值的微妙之处...
\33[2K
删除光标当前所在的整行
\033[A
将光标上移一行,但移至同一列,即不移至该行的开头
\r
将光标移至该行的开头(r用于回车NB回车不包括换行符,因此光标保持在同一行)但不会擦除任何内容
具体来说,在xterm中,我尝试了上述答复,发现删除行并从头开始重新开始的唯一方法是序列(来自@ Stephan202以及@vlp和@mantal的上述注释) \33[2K\r
在实施注意事项上,为了使它在倒数计时的情况下正常工作,因为我没有'\n'
在每个末尾使用换行符fprintf()
,所以我每次都必须进行fflush()
流处理(为了给您一些上下文,我开始xterm在Linux机器上使用fork而不重定向stdout,我只是fdfile
使用非阻塞文件描述符写入缓冲的FILE指针,而该描述符位于伪终端地址上,在本例中为/dev/pts/21
):
fprintf(fdfile, "\33[2K\rT minus %d seconds...", i);
fflush(fdfile);
请注意,我同时使用\ 33 [2K序列来擦除该行,然后使用\r
回车序列来将光标重新定位在该行的开头。我fflush()
每次都不得不fprintf()
这么做,因为最后没有换行符'\n'
。不需要fflush()的相同结果将需要附加的序列上一行:
fprintf(fdfile, "\033[A\33[2K\rT minus %d seconds...\n", i);
请注意,如果在要写入的行的正上方有行,则第一个fprintf()会覆盖该行。您将不得不在上面多留一行,以允许第一行向上移动:
i = 3;
fprintf(fdfile, "\nText to keep\n");
fprintf(fdfile, "Text to erase****************************\n");
while(i > 0) { // 3 second countdown
fprintf(fdfile, "\033[A\33[2KT\rT minus %d seconds...\n", i);
i--;
sleep(1);
}
\r
是“回车”而不是“倒带”的缩写,是老式打字机的遗物,它们分别用于“将光标移回第一列”(\r
)和“将页面前进到下一行”(\n
)的操作。
\33[2K
是一条路!对我来说最好的问题解决方案。也可在Windows ConEmu上使用
通常,当字符串末尾带有“ \ r”时,仅打印回车符而没有换行符。如果您具有以下条件:
printf("fooooo\r");
printf("bar");
输出将是:
barooo
我可以建议的一件事(也许是一种解决方法)是让一个以NULL终止的固定大小的字符串初始化为所有空格字符,并以'\ r'结尾(每次打印之前),然后使用strcpy将您的字符串复制到它(没有换行符),因此每个后续打印都会覆盖前一个字符串。像这样:
char str[MAX_LENGTH];
// init str to all spaces, NULL terminated with character as '\r'
strcpy(str, my_string); // copy my_string into str
str[strlen(my_string)] = ' '; // erase null termination char
str[MAX_LENGTH - 1] = '\r';
printf(str);
您可以进行错误检查,以使my_string
长度总是至少比少一倍str
,但是您已经掌握了基本思想。
i
遍历char数组字。 j
跟踪字长。 "\b \b"
在回退时擦除单词。
#include<stdio.h>
int main()
{
int i = 0, j = 0;
char words[] = "Hello Bye";
while(words[i]!='\0')
{
if(words[i] != ' ') {
printf("%c", words[i]);
fflush(stdout);
}
else {
//system("ping -n 1 127.0.0.1>NUL"); //For Microsoft OS
system("sleep 0.25");
while(j-->0) {
printf("\b \b");
}
}
i++;
j++;
}
printf("\n");
return 0;
}
有一个简单的技巧可以在这里工作,但是需要在打印之前进行准备,您必须将要打印的内容放入变量中然后再打印,这样才能知道删除字符串的长度。这里有一个例子。
#include <iostream>
#include <string> //actually this thing is not nessasory in tdm-gcc
using namespace std;
int main(){
//create string variable
string str="Starting count";
//loop for printing numbers
for(int i =0;i<=50000;i++){
//get previous string length and clear it from screen with backspace charactor
cout << string(str.length(),'\b');
//create string line
str="Starting count " +to_string(i);
//print the new line in same spot
cout <<str ;
}
}
刚刚找到了这个旧线程,寻找某种转义序列来清空实际行。
没有人想到printf返回写入的字符数的想法(或者我错过了),这很有趣。因此,只需打印'\ r'+与返回的printf一样多的空白字符,您就可以完全空白的先前写入的文本。
int BlankBytes(int Bytes)
{
char strBlankStr[16];
sprintf(strBlankStr, "\r%%%is\r", Bytes);
printf(strBlankStr,"");
return 0;
}
int main(void)
{
int iBytesWritten;
double lfSomeDouble = 150.0;
iBytesWritten = printf("test text %lf", lfSomeDouble);
BlankBytes(iBytesWritten);
return 0;
}
由于我无法使用VT100,因此似乎必须坚持使用该解决方案
echo -e "hello\c" ;sleep 1 ; echo -e "\rbye "
上面的命令将做什么:
它将打印问候,并且光标将保持在“ o”(使用\ c)
然后它将等待1秒(睡眠1)
然后它将用bye代替hello。(使用\ r)
NOTE : Using ";", We can run multiple command in a single go.
在Windows 10下,可以通过在当前控制台中激活VT100模式以使用转义序列来使用VT100样式,如下所示:
#include <windows.h>
#include <iostream>
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
#define DISABLE_NEWLINE_AUTO_RETURN 0x0008
int main(){
// enabling VT100 style in current console
DWORD l_mode;
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleMode(hStdout,&l_mode)
SetConsoleMode( hStdout, l_mode |
ENABLE_VIRTUAL_TERMINAL_PROCESSING |
DISABLE_NEWLINE_AUTO_RETURN );
// create a waiting loop with changing text every seconds
while(true) {
// erase current line and go to line begining
std::cout << "\x1B[2K\r";
std::cout << "wait a second .";
Sleep(1);
std::cout << "\x1B[2K\r";
std::cout << "wait a second ..";
Sleep(1);
std::cout << "\x1B[2K\r";
std::cout << "wait a second ...";
Sleep(1);
std::cout << "\x1B[2K\r";
std::cout << "wait a second ....";
}
}
参见以下链接:Windows VT100