如何在终端中更新打印的消息而不重新打印

问题描述 投票:39回答:8

我想为我的终端应用程序创建一个进度条,它的工作方式如下:

 [XXXXXXX       ] 

这将在过程完成之前提供剩余时间的可视指示。

我知道我可以通过将它们添加到字符串然后只是printf来打印越来越多的X,但这看起来像:

 [XXXXXXX       ] 
 [XXXXXXXX      ] 
 [XXXXXXXXX     ] 
 [XXXXXXXXXX    ] 

或类似的东西(显然你可以玩间距。)但这在视觉上不美观。有没有办法用新文本更新终端中的打印文本而无需重新打印?这都是linux,c ++。

c++ linux text terminal
8个回答
43
投票

在打印新的“版本”时尝试使用\r而不是\n

for(int i=0;i<=100;++i) printf("\r[%3d%%]",i);
printf("\n");

10
投票

我会说像ncurses这样的库会用于这样的事情。 curses有助于在屏幕上移动光标并绘制文本等。

NCurses


7
投票

像这样的东西:

std::stringstream out;
for (int i = 0; i< 10; i++)
{
  out << "X";
  cout << "\r" << "[" << out.str() << "]";
}

偷偷摸摸的位是回车符“\ r”,它使光标移动到行的开头而不会下到下一行。


3
投票

其他人已经指出你可以使用\r回到当前行的开头,并覆盖整行。

另一种可能性是使用退格符(“\ b”)来擦除一些空格,并仅覆盖那些空格。这可以有几个优点。首先,它显然避免了必须重新生成线上的所有东西,这有时可能是轻微的痛苦(虽然这是相当不寻常的)。其次,它可以避免显示数据时出现一些痛苦(例如)在写入时缩小尺寸 - 例如,如果你显示从100到0的倒计时,使用\r你必须要小心覆盖整个前一个长度,或者你的倒计时将从(例如)100变为990(即,保留前一个“0”完整)。

但请注意,虽然行内的后退空间通常有效,但行开头的退格可能会或可能不会将光标/写入位置移回前一行。对于大多数实际用途,您只能在一行内移动。


1
投票

'\ r'将执行回车。想象一下打印机在没有换行符('\ n')的情况下进行回车。这将使写入点返回到行的开头...然后在原始行的顶部重新打印更新的状态。


1
投票

这是一种不同的语言,但this question可能对你有所帮助。基本上,转义字符\ r \ n(回车符,而不是\ n换行符)会将您移回当前打印行的开头,以便您可以覆盖已打印的内容。


1
投票

另一种选择是一次只打印一个字符。通常,stdout是行缓冲的,所以你需要调用fflush(stdout) -

for(int i = 0; i < 50; ++i) {
   putchar('X'); fflush(stdout);
   /* do some stuff here */
}
putchar('\n');

但这没有表明完成的好终止“]”。


0
投票

我前段时间写过这个加载栏工具。可能有用......

https://github.com/BlaDrzz/CppUtility/tree/master/LoadingBar

你可以在这里自定义任何东西。

int max = 1000;
LoadingBar* lb = new LoadingBar(10, 0, max);

for (size_t i = 0; i <= max; i++)
{
    lb->print();
    lb->iterate();
}
cout << lb->toString() << endl;

非常简单和可定制的实现..

© www.soinside.com 2019 - 2024. All rights reserved.