Linux 擦除当前打印的控制台行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1508490/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Erase the current printed console line
提问by
How can I erase the current printed console line in C? I am working on a Linux system. For example -
如何擦除 C 中当前打印的控制台行?我在 Linux 系统上工作。例如 -
printf("hello");
printf("bye");
I want to print bye on the same line in place of hello.
我想在同一行打印 bye 代替 hello。
采纳答案by mouviciel
You can use VT100 escape codes. Most terminals, including xterm, are VT100 aware. For erasing a line, this is ^[[2K
. In C this gives:
您可以使用VT100 转义码。大多数终端,包括 xterm,都支持 VT100。为了擦除一条线,这是^[[2K
。在 C 中,这给出:
printf("%c[2K", 27);
回答by Andre Miller
You can use a \r
(carriage return) to return the cursor to the beginning of the line:
您可以使用\r
(回车)将光标返回到行首:
printf("hello");
printf("\rbye");
This will print byeon the same line. It won't erase the existing characters though, and because byeis shorter than hello, you will end up with byelo. To erase it you can make your new print longer to overwrite the extra characters:
这将在同一行打印再见。但是它不会删除现有的字符,因为bye比hello短,你最终会得到byelo。要擦除它,您可以延长新打印的时间以覆盖额外的字符:
printf("hello");
printf("\rbye ");
Or, first erase it with a few spaces, then print your new string:
或者,先用几个空格擦除它,然后打印你的新字符串:
printf("hello");
printf("\r ");
printf("\rbye");
That will print hello, then go to the beginning of the line and overwrite it with spaces, then go back to the beginning again and print bye.
这将打印hello,然后转到该行的开头并用空格覆盖它,然后再次返回开头并打印bye。
回答by Ashwin
Usually when you have a '\r' at the end of the string, only carriage return is printed without any newline. If you have the following:
通常,当字符串末尾有一个 '\r' 时,只会打印回车而没有任何换行符。如果您有以下情况:
printf("fooooo\r");
printf("bar");
the output will be:
输出将是:
barooo
One thing I can suggest (maybe a workaround) is to have a NULL terminated fixed size string that is initialized to all space characters, ending in a '\r' (every time before printing), and then use strcpy to copy your string into it (without the newline), so every subsequent print will overwrite the previous string. Something like this:
我可以建议的一件事(可能是一种解决方法)是有一个以 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);
You can do error checking so that my_string
is always atleast one less in length than str
, but you get the basic idea.
你可以做错误检查,这样它的my_string
长度总是至少比 少一个str
,但你得到了基本的想法。
回答by Alexander Egger
You could delete the line using \b
您可以使用 \b 删除该行
printf("hello");
int i;
for (i=0; i<80; i++)
{
printf("\b");
}
printf("bye");
回答by Paul T
i
iterates through char array words. j
keeps track of word length. "\b \b"
erases word while backing over line.
i
遍历字符数组单词。 j
跟踪字长。 "\b \b"
在回退行时擦除单词。
#include<stdio.h>
int main()
{
int i = 0, j = 0;
char words[] = "Hello Bye";
while(words[i]!='#include <stdio.h>
int main ()
{
//write some input
fputs("hello\n",stdout);
//wait one second to change line above
sleep(1);
//remove line
fputs("3[A3[2K",stdout);
rewind(stdout);
//write new line
fputs("bye\n",stdout);
return 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;
}
回答by vlp
回答by J-a-n-u-s
Some worthwhile subtleties...
一些有价值的微妙之处......
\33[2K
erases the entire line your cursor is currently on
\33[2K
擦除光标当前所在的整行
\033[A
moves your cursor up one line, but in the same columni.e. not to the start of the line
\033[A
将光标向上移动一行,但在同一列中,即不移动到行首
\r
brings your cursor to the beginning of the line (r is for carriage return N.B. carriage returns do not include a newline so cursor remains on the same line) but does noterase anything
\r
将光标移至行首(r 用于回车 NB 回车不包括换行符,因此光标保留在同一行上)但不会擦除任何内容
In xterm specifically, I tried the replies mentioned above and the only way I found to erase the line and start again at the beginning is the sequence (from the comment above posted by @Stephan202 as well as @vlp and @mantal) \33[2K\r
特别是在 xterm 中,我尝试了上面提到的回复,我发现擦除行并从头开始的唯一方法是序列(来自@Stephan202 以及@vlp 和@mantal 发布的上述评论) \33[2K\r
On an implementation note, to get it to work properly for example in a countdown scenario since I wasn't using a new line character '\n'
at the end of each fprintf()
, so I had to fflush()
the stream each time (to give you some context, I started xterm using a fork on a linux machine without redirecting stdout, I was just writing to the buffered FILE pointer fdfile
with a non-blocking file descriptor I had sitting on the pseudo terminal address which in my case was /dev/pts/21
):
在实现说明中,为了让它在倒计时场景中正常工作,因为我没有'\n'
在 each 的末尾使用换行符fprintf()
,所以我每次都必须fflush()
使用流(为了给你一些上下文,我开始xterm 在 linux 机器上使用 fork 而不重定向标准输出,我只是fdfile
用非阻塞文件描述符写入缓冲的 FILE 指针,我坐在伪终端地址上,在我的情况下是/dev/pts/21
):
fprintf(fdfile, "3[A[2K\rT minus %d seconds...\n", i);
Note that I used both the \33[2K sequence to erase the line followed by the \r
carriage return sequence to reposition the cursor at the beginning of the line. I had to fflush()
after each fprintf()
because I don't have a new line character at the end '\n'
. The same result without needing fflush() would require the additional sequence to go up a line:
请注意,我同时使用了 \33[2K 序列来擦除该行,然后使用\r
回车序列将光标重新定位在该行的开头。我不得不fflush()
在每个之后,fprintf()
因为我最后没有换行符'\n'
。不需要 fflush() 的相同结果将需要额外的序列上升一行:
i = 3;
fprintf(fdfile, "\nText to keep\n");
fprintf(fdfile, "Text to erase****************************\n");
while(i > 0) { // 3 second countdown
fprintf(fdfile, "3[A[2KT\rT minus %d seconds...\n", i);
i--;
sleep(1);
}
Note that if you have something on the line immediately above the line you want to write on, it will get over-written with the first fprintf(). You would have to leave an extra line above to allow for the first movement up one line:
请注意,如果您在要写入的行正上方的行上有内容,它将被第一个 fprintf() 覆盖。您必须在上面多留一行,以便第一次向上移动一行:
#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 ;
}
}
回答by Aylian Craspa
there is a simple trick you can work here but it need preparation before you print, you have to put what ever you wants to print in a variable and then print so you will know the length to remove the string.here is an example.
有一个简单的技巧,您可以在这里工作,但在打印之前需要准备,您必须将想要打印的内容放入变量中,然后打印,以便您知道删除字符串的长度。这是一个示例。
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;
}
回答by David
Just found this old thread, looking for some kind of escape sequence to blank the actual line.
刚刚找到这个旧线程,寻找某种转义序列来空白实际行。
It's quite funny no one came to the idea (or I have missed it) that printf returns the number of characters written. So just print '\r' + as many blank characters as printf returned and you will exactly blank the previuosly written text.
有趣的是没有人想到(或者我已经错过了) printf 返回写入的字符数。因此,只需打印 '\r' + 与 printf 返回的空白字符一样多的空白字符,您将完全空白先前写入的文本。
echo -e "hello\c" ;sleep 1 ; echo -e "\rbye "
As I cant use VT100, it seems I have to stick with that solution
由于我无法使用 VT100,看来我必须坚持使用该解决方案
回答by Ayush Mahajan
What the above command will do :
上面的命令会做什么:
It will print hello and the cursor will remain at "o" (using \c)
Then it will wait for 1 sec (sleep 1)
Then it will replace hello with bye.(using \r)
它将打印 hello 并且光标将保持在“o”(使用 \c)
然后它将等待 1 秒(睡眠 1)
然后它将用再见替换你好。(使用\ r)
NOTE : Using ";", We can run multiple command in a single go.
NOTE : Using ";", We can run multiple command in a single go.