從一個進度條看問題

1.前言

我們要實現關於一個進度條,我們的想法是採用for循環的方式,所以對於這個進度條,我們需要從下面幾個問題來一一看待問題。

2.關於 ‘\n’ 與 ‘\r’


這兩個符號,一個叫做回車,一個叫做換行,好多人對這兩個分不清,所以我們在這裏需要介紹一下。
在最早的時候,只有打字機的時候,人們在每行的後面加上兩個表示結束的字符,一個叫做回車,它把打字機的光標定位在左邊界,另外一個是換行,它用來換到下一行,這個就是所說的回車和換行的由來。

對於在linux和windows當中,’\r’和’\n’的方式也是有區別。
在windows,每行的結尾是回車+換行,
在linux下,每行的結尾是換行。

Linux中遇到換行符(“\n”)會進行回車+換行的操作,回車符反而只會作爲控制字符(“^M”)顯示,不發生回車的操作。而windows中要回車符+換行符(“\r\n”)纔會回車+換行,缺少一個控制符或者順序不對都不能正確的另起一行。

對於這個區別,同樣影響了我們在windows平臺下和linux下使用fopen函數打開文本文件的時候,在我前期在一個項目,文件壓縮項目中曾經遇到過這樣的問題,當我們將windows按照文本的方式進行讀取的時候,這個時候會把每行最後讀出兩個字符,一個換行一個回車。所以當時我們最終採用了二進制的方式進行讀取。

清楚了這個概念,所以我們接下來進行進度條的操作時,我們只需要進行每次的’\r’,這樣我們就可以每一次進行對該行的重新打印。最終,就可以實現所要求的一個進度條功能。

3.關於print緩衝區的問題


我們通過對操作系統的學習,知道了對於我們所printf打印的內容,那麼就是需要將內容首先放到內存,讓後通過內存提供內容給顯示器顯示。但是對於操作系統來說,顯示器是一個外設,速度慢,所以爲了平衡,提供了一個緩衝區來進行操作,內存吧數據給了緩衝區,接下來的輸出就由緩衝區進行操作了,內存就不管了。

linux下的每一個進程會維護一個print/scanf的緩衝區,對於緩衝區而言,緩衝區有一個概念叫做緩衝方式,就是說達到一定的方式,緩衝區的內容纔會被刷新。

標C庫函數自帶緩衝區 ,常見的三種緩衝方式:
(1)行緩衝:遇到”\n”,就會刷新緩衝區
(2)全緩衝:把緩衝區寫滿,再進行刷新緩衝區
(3)無緩衝:系統調用函數無緩衝區(如:write)

默認情況下,一般採用行緩衝方式。

當程序退出緩衝區自動刷新,也就是一個進程結束的時候,當使用scanf也會刷新。
所以,爲了每次進行打印每行的內容,我們需要採用強制刷新緩衝區,這裏有一個函數fflush()。

好,接下來的打印就是輕鬆加愉快。
所以框架我們已經搭建好了,剩下的我們就是進行考慮寫法了,爲了實現整個進度條,我們模仿linux下的那種進度條,我們給一個定長數組實現。

#include<stdio.h>
#include<unistd.h>
#include<string.h>
void procbar()
{
    char arr[102];

    int rate=0;
    char tmp[]="-\\|/";
    memset(arr,0,sizeof(arr));
    while(rate<=100)
    {
        printf("[%-100s][%d%%][%c]\r",arr,rate,tmp[rate%4]);               //在這裏注意printf格式,我們讓進度條定長,並且左對齊方式打印。

        arr[rate]='=';
        rate++;
        fflush(stdout);                                   //進行強制刷新,因爲這裏是在進行輸出,所以要刷新的當然是輸出流。

        usleep(100000);
    }
    printf("\n");
}
int main()
{
    procbar();
    return 0;
}

最後的實驗結果:
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章