2009-08-26 52 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」完好)。

但是,請注意,儘管行內的後退空間通常有效,但行開始處的退格可能會或可能不會將光標/寫入位置移回上一行。對於大多數實際目的,您只能在一行內移動。