在Linux下實現簡易進度條
本文將要概述
- printf的緩衝區問題;
- \r和\n的區別;
- 如何實現一個簡易的進度條;
奇怪的現象
進度條是安裝和下載軟體中常見的部分,它可以表示軟體安裝或下載了多大,能給客戶一種直觀的感受,今天我們就來實現一個簡易的進度條,基本構思是這樣的,我們定義一個大小為102的字元陣列,其中100個用來儲存‘#’,每跑了進度條的1%它就會在字元陣列中增長一個該符號。還有兩塊空間用於存放’\0’,和防止死迴圈問題(這是因為控制迴圈的變數被定義在陣列的後面一塊空間,對陣列訪問造成了越界的話很有可能修改這塊空間的值,從而造成不可預料的後果)所以我們多開闢一塊空間,避免這種情況的發生。
程式的思路是這樣的,每一次迴圈都往字元陣列中的當前位置寫入’#’,並將控制迴圈變數+1,在寫入’#’的下一個人位置寫入’\0’,防止列印字元陣列時出現亂碼。迴圈次數控制在100次,每輸入1行後我們輸入\r對其清空,由於延時時間段和人眼的視覺暫留效應,你會看到進度條是一個一個#增長的。
理論上你應該看到這樣的效果
[# ]
[## ]
.
.
.
[############################## ]
[############################### ]
[################################]
程式碼如下
由於本人這裡沒有截動態圖的軟體,當程式寫好後通過gcc編譯成可執行檔案直接執行你會看到進度條並不會像你想象的那樣增長。它是一次好幾個#號的增長直到#增長到100個位置。
這是為什麼呢????????
下面我們就來揭祕一下這個現象的原因!!!!!
printf的緩衝區問題
出現上面這種原因首先肯定是由於\r的效果,我們再來修改一下程式,把\r換成\n看看會出現什麼現象。
真是不吹不黑,咱們來看一下效果,特別是#每次的增長個數;
這時我只截圖一部分的效果。
結合著\n和\r的現象我們來引入一個知識點,printf的緩衝區問題
出現上面的兩種情況,是因為printf是一個行緩衝函式
重新整理緩衝區只要滿足下面任意一個條件即可:
1. 緩衝區填滿
2. 寫入的字元中有‘\n’
3. 呼叫fflush手動重新整理緩衝區
4. 呼叫scanf要從緩衝區中讀取資料時,也會將緩衝區內的資料重新整理
可見每次我們寫入\r是不能夠重新整理緩衝區的,只會等緩衝區慢後才會將字串列印到螢幕上,那麼我們想要實現一個進度條,就不能夠用\n字元,我們必須要在一行上對緩衝區進行重新整理,於是我們每次寫入到緩衝區時,都用fflush函式重新整理一下緩衝區,問題是不是就能解決了呢?實踐出真知,還是讓我們修改下程式碼看看結果吧!
事實是大功告成了!!!
所修改的程式碼
由於printf是輸出緩衝區,所以我們需要重新整理下stdout,我們可以男人(man)一下看看這個stdout是幹什麼的。
總結
好了,今天我們主要談到了printf的輸出緩衝區的問題,進度條的實現依賴於每次寫進緩衝區後都要重新整理緩衝區,使緩衝區中的字元輸出到螢幕上。