2009-08-26 54 views
37

我想为我的终端应用程序的进度条,将工作是这样的:如何更新终端的印刷信息不重印(Linux)的

[XXXXXXX  ] 

这将使多少时间的视觉指示过程完成之前还有剩余。

我知道我可以这样做将它们添加到字符串,然后简单的printf打印越来越X的,但是这将是这样的:

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

或类似的东西(很明显,你可以玩间距)。但这不是视觉美学。有没有办法用新文本更新终端中的打印文本而不重新打印?这全部在linux下,C++。

回答

40

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

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

作品像一个魅力,谢谢 – ldog 2009-08-26 21:32:17

8

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

NCurses

+6

听起来像在这里矫枉过正。 – 2009-08-26 21:20:24

+1

是的,可能...只是一个建议,如果有人想在未来获得更多的幻想;) – KFro 2009-08-26 21:23:43

+3

是的......当我们等待进度条时,可能会有PONG游戏继续进行。 :D – kjfletch 2009-08-26 21:30:36

6

事情是这样的:

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

偷偷摸摸位是回车符“\ r”,这使光标移动到行的开始而不会延续到下一个线。

1

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

1

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

1

另一种选择是一次只打印一个字符。通常情况下,标准输出行缓冲,所以你需要调用fflush(标准输出) -

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

但是,这并不具备很好的终结“]”,表示完成。

3

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

另一种可能性是使用退格字符(“\ b”)擦除几个空格,并只覆盖那些空格。这可以具有几个优点。首先,它显然避免了必须重新生成一行中的所有内容,有时可能会带来轻微的痛苦(尽管这非常不寻常)。其次,它可以避免在显示数据时出现一些痛苦(例如,在您编写数据时)缩小的数据 - 例如,如果您显示的计数从100减至0,则需要注意\r覆盖整个以前的长度,或者倒计数将从(例如)100到990(即,保持前面的“0”完好)。

但是,请注意,尽管行内的后退空间通常有效,但行开始处的退格可能会或可能不会将光标/写入位置移回上一行。对于大多数实际目的,您只能在一行内移动。