這篇博客要綜合利用以前的知識,來實(shí)現(xiàn)一個進(jìn)度條程序~
目錄
換行&回車
緩沖區(qū)
實(shí)現(xiàn)簡單的倒計(jì)時
實(shí)現(xiàn)進(jìn)度條
version1
version2
?文章來源地址http://www.zghlxwxcb.cn/news/detail-838076.html
在開始寫這個小程序之前,我們先學(xué)習(xí)一些預(yù)備知識:
換行&回車
緩沖區(qū)
?在我們運(yùn)行這個程序時,并沒有直接打印出“hello bit,hello world...”,而是當(dāng)程序運(yùn)行結(jié)束后才顯示出來,但是這并不代表這句打印沒有執(zhí)行,而是沒有顯示出來而已。
那么,在我sleep期間,字符串在哪里?
答案就是被保存在叫做緩沖區(qū)的地方,就是一塊內(nèi)存空間,當(dāng)程序結(jié)束時,一般會自動刷新緩沖區(qū)到字符設(shè)備(顯示器),另外,如果程序遇到‘\n’的時候,也會刷新緩沖區(qū)。如果想要強(qiáng)制刷新,可以使用fflush命令。
那么,為什么要有緩沖區(qū)呢,為什么按行刷新?為了提高效率,方便人類閱讀,人類讀信息都是按行讀的,是一種尊重用戶的表現(xiàn)。
?實(shí)現(xiàn)簡單的倒計(jì)時
在實(shí)現(xiàn)倒計(jì)時中,我們想要達(dá)到的效果是依次顯示數(shù)字,并且下一個覆蓋前一個數(shù)字,創(chuàng)建test.c文件:
1 #include <stdio.h>
2 #include <unistd.h>
3
4 int main()
5 {
6 int cnt=10;
7 while(cnt >=0)
8 {
9 printf("倒計(jì)時:%2d\r",cnt);
10 fflush(stdout);
11 cnt--;
12 sleep(1);
13 }
14 printf("\n");
15
16 return 0 ;
17 }
我們實(shí)現(xiàn)的效果是10,9,...1,0的倒計(jì)時效果,其中,
printf("倒計(jì)時:%2d\r",cnt);
這句代碼中\(zhòng)r是回車,在一次打印完成后,光標(biāo)回到最前面,繼續(xù)打印下一個值,覆蓋掉上一次的值,用%2d的格式打印的原因是,每次打印兩個字符,以防某個字符一直在屏幕上顯示。使用fflush(stdout)強(qiáng)制刷新到顯示器上。
此外,我們還寫了makefile自動化構(gòu)建工具:
mycode:test.c
2 gcc -o $@ $^
3 .PHONY:clean
4 clean:
5 rm -f mycode
至此完成了簡單的倒計(jì)時效果。
實(shí)現(xiàn)進(jìn)度條
version1
在實(shí)現(xiàn)進(jìn)度條中,我們要創(chuàng)建三個文件:Processbar.h,Processbar.c,Main.c,Main.c負(fù)責(zé)將Processbar.h中的方法進(jìn)行調(diào)用,最終想達(dá)到的效果如下圖:
在Processbar.h中,我們定義了Process函數(shù)聲明;
#pragma once
#include <stdio.h>
extern void Process();
在Processbar.c中實(shí)現(xiàn)了Process:
#include "Processbar.h"
#include <string.h>
#include <unistd.h>
#define Length 101
#define Style '#'
const char * label = "|/-\\";
// version1
void Process()
{
char bar[Length];
memset(bar,'\0',sizeof(bar));
int cnt = 0;
int len =strlen(label);
while(cnt <= 100)
{
printf("[%-100s][%3d%%][%c]\r",bar,cnt,label[cnt%len]);
fflush(stdout);
bar[cnt++]=Style;
usleep(20000);
}
printf("\n");
}
在上面這段程序中,我們用bar數(shù)組來實(shí)現(xiàn)進(jìn)度條,大小Length設(shè)為101(包括最后的‘\0’),進(jìn)度條符號為‘#’。[%-100s]表示字符串靠左對齊,保證了‘#’從左邊往右增長。通過循環(huán)遍歷label所指向的數(shù)組來實(shí)現(xiàn)旋轉(zhuǎn)光標(biāo)的效果。
需要注意的是,因?yàn)槊看问褂谩甛r’來實(shí)現(xiàn)覆蓋的效果,但是‘\r’不能讓每次結(jié)果刷新到顯示器上,需要用fflush(stdout)來刷新。usleep()函數(shù)的單位是微秒(包含unistd.h頭文件)。
在Main.c中,調(diào)用Process.h:
#include "Processbar.h"
int main() {
Process();
return 0;
}
最終的實(shí)現(xiàn)效果:
version2
上面我們單獨(dú)寫了一個進(jìn)度條程序,但是,進(jìn)度條會單獨(dú)出現(xiàn)嗎?肯定不會!它要和具體的場景結(jié)合。
假設(shè)我們要完成一個下載的場景:下載指定大小的文件,
在Main.c中,我們寫出download()這樣一個函數(shù):
double bandwidth = 1024*1024*1.0;
//download
void download(double filesize,callback_t cb)
{
//double filesize = 100*1024*1024*1.0;
double current = 0.0;
printf("download begin,current:%lf\n",current);
while(current <= filesize)
{
cb(filesize,current);
//從網(wǎng)絡(luò)中獲取
current += bandwidth;
usleep(10000);
}
printf("\ndownload done,filesize:%lf\n",filesize);
}
其中,bandwidth是我們假設(shè)的帶寬(可以理解為下載速度),download函數(shù)的filesize參數(shù)是我們要下載的文件大小,第二個參數(shù)是進(jìn)度條打印函數(shù),callback_t是函數(shù)指針,其定義在Processbar.h中,
typedef void(*callback_t)(double,double);
在while循環(huán)中,根據(jù)filesize和current的大小,打印出當(dāng)前下載進(jìn)度的進(jìn)度條,打印完成后,繼續(xù)下載,current繼續(xù)增加,然后再打印下一次的進(jìn)度條并覆蓋之前的進(jìn)度條。
在Processbar.h中,有如下聲明:
#pragma once
#include <stdio.h>
typedef void(*callback_t)(double,double);
void Process(double total,double current);
在Processbar.c中,定義了Process函數(shù):
//version2
void Process(double total,double current)
{
char bar[Length];
memset(bar,'\0',sizeof(bar));
int cnt = 0;
int len =strlen(label);
double rate = current*100.0/total;
int loop_count = (int)rate;
while(cnt <= loop_count)
{
bar[cnt++]=Style;
}
printf("[%-100s][%.1lf%%][%c]\r",bar,rate,label[cnt%len]);
fflush(stdout);
}
根據(jù)總文件大小total和當(dāng)前已下載大小current,打印出當(dāng)前的進(jìn)度條,例如,當(dāng)total=100、current=36時,會打印出如下內(nèi)容:
在Main.c中,將Process函數(shù)作為實(shí)參傳給download()函數(shù),完成下載。
int main()
{
download(100*1024*1024,Process);
download(50*1024*1024,Process);
download(80*1024*1024,Process);
download(1*1024*1024,Process);
download(18*1024*1024,Process);
return 0;
}
?模擬下載了多個文件,其效果如下:
文章來源:http://www.zghlxwxcb.cn/news/detail-838076.html
?
到了這里,關(guān)于【Linux】第一個小程序--進(jìn)度條的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!