
1. 預(yù)備知識(shí)
1.1 簡單認(rèn)識(shí)幾個(gè)函數(shù)
1.1.1 sleep()
unsigned int sleep(unsigned seconds);
- 作用:讓程序休眠指定秒數(shù),如:
sleep(3); //讓程序休眠3秒
- 與 Windows 上的 Sleep() 函數(shù)不同
- 需要包含頭文件
<unistd.h>
1.1.2 fflush()
int fflush(FILE* stream);
- 作用:刷新緩沖區(qū)
- 需要傳入一個(gè)流
- 需要包含頭文件
<stdio.h>
1.1.3 usleep()
int usleep(useconds_t usec);
- 作用:讓程序休眠指定微秒,如:
usleep(100000); //讓程序休眠100000微秒(0.1秒)
- 1秒 = 1000000微秒
- 需要包含頭文件
<unistd.h>
1.1.4 memset()
void* memset(void* ptr, int value, size_t num);
- 作用:將 ptr 指向的內(nèi)存塊的前 num 個(gè)字節(jié)設(shè)置為指定的 value 值
- 返回設(shè)置后的 ptr
- 需要包含頭文件
<string.h>
1.2 緩沖區(qū)
直接上代碼觀察現(xiàn)象
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("you can see me ");
sleep(3);
return 0;
}
執(zhí)行效果圖
- 首先要否定上面不切實(shí)際的想法,C語言是順序執(zhí)行的,所以 printf 函數(shù)一定先于 sleep 函數(shù)執(zhí)行。
- 那為什么 3 秒后才打印到屏幕上呢?當(dāng)然是因?yàn)榫彌_區(qū)!
- printf 函數(shù)跑完后,輸出的字符串是被保存到 C 對(duì) IO 函數(shù)提供的一個(gè)緩沖區(qū)里了,在程序退出的時(shí)候,緩沖區(qū)中的內(nèi)容才被刷新到屏幕上。
- 我們需要使用上面講的 fflush 函數(shù)把緩沖區(qū)中的內(nèi)容提前強(qiáng)制刷新到屏幕上,使用方法:
fflush(stdout);
1.3 回車與換行
首先我要拋出一個(gè)概念:回車和換行是不一樣的!
- 回車( \r ):把光標(biāo)放到當(dāng)前行的開始。
- 換行( \n ):把光標(biāo)放到當(dāng)前位置的下一行。
- 所以理論上來講,‘\n’ 和 ‘\r’ 一起用才是我們理解中的”回車“,即:把光標(biāo)放到下一行最開始的位置。
2. 編寫入門版的進(jìn)度條
2.1 基本邏輯
- 進(jìn)度 1% 打印 1 個(gè)字符,回車到開始的位置,刷新緩沖區(qū);
- 進(jìn)度 2% 打印 2 個(gè)字符,回車到開始的位置,刷新緩沖區(qū);
- …
- 進(jìn)度 100% 打印 100 個(gè)字符,回車到開始的位置,刷新緩沖區(qū),程序終止。
2.2 美化效果
- 進(jìn)度條主體增加箭頭顯示
- 顯示進(jìn)度百分比
- 添加一個(gè)動(dòng)態(tài)的旋轉(zhuǎn)光標(biāo)
2.3 代碼實(shí)現(xiàn)
// porcessbar.h
#pragma once
#include <stdio.h>
#define NUM 103
#define Body '='
#define Head '>'
// version 1
void process();
// processbar.c
#include "processbar.h"
#include <string.h>
#include <unistd.h>
const char* lable = "|/-\\";
// version 1
void process()
{
char buffer[NUM];
memset(buffer, '\0', sizeof(buffer));
int cnt = 0;
int n = strlen(lable);
buffer[0] = Head;
while (cnt <= 100)
{
printf("[%-100s][%3d%%][%c]\r", buffer, cnt, lable[cnt % n]);
fflush(stdout);
buffer[cnt++] = Body;
if (cnt < 100)
{
buffer[cnt] = Head;
}
usleep(50000);
}
printf("\n");
}
2.4 執(zhí)行效果
3. 編寫升級(jí)版的進(jìn)度條
- 上面的進(jìn)度條算是一個(gè)進(jìn)度條嗎?我們的進(jìn)度條似乎在一個(gè)人玩單機(jī)呀,這樣的進(jìn)度條是沒有意義的。
- 進(jìn)度條的進(jìn)度應(yīng)該是依賴于其他應(yīng)用的,比如下載。
- 下面我們模擬一個(gè)下載環(huán)境,并修改進(jìn)度條,使進(jìn)度條可以根據(jù)下載的進(jìn)度,同步進(jìn)行顯示進(jìn)度的工作。
3.1 代碼實(shí)現(xiàn)
// processbar.h
#pragma once
#include <stdio.h>
#define NUM 103
#define Body '='
#define Head '>'
typedef void (*callback_t)(double); // 函數(shù)指針類型
// version 2
void process_flush(double rate);
// processbar.c
#include "processbar.h"
#include <string.h>
#include <unistd.h>
const char* lable = "|/-\\";
// version 2: 進(jìn)度是多少,你進(jìn)度條能知道嗎?另外,什么進(jìn)度?依附于其他應(yīng)用的,比如下載
char buffer[NUM] = {0};
void process_flush(double rate)
{
static int cnt = 0;
int n = strlen(lable);
if (rate <= 1.0)
{
buffer[0] = Head;
}
printf("[%-100s][%.1f%%][%c]\r", buffer, rate, lable[cnt % n]);
fflush(stdout);
buffer[(int)rate] = Body;
if ((int)rate + 1 < 100)
{
buffer[(int)(rate + 1)] = Head;
}
if (rate >= 100.0)
{
printf("\n");
}
cnt++;
cnt %= n;
}
// main.c
#include "processbar.h"
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
// 模擬文件大小
#define FILESIZE (1024 * 1024 * 1024)
// 模擬一種場景,表示一種下載任務(wù)
void download(callback_t cb) // 回調(diào)函數(shù)的形式
{
srand(time(NULL) ^ 1023); // 這樣寫只是為了讓隨機(jī)數(shù)更隨機(jī)
int total = FILESIZE;
while (total)
{
usleep(10000); // 下載動(dòng)作
int one = rand() % (1024 * 1024); // 一次下載的大小
total -= one;
if (total < 0)
{
total = 0;
}
// 當(dāng)前的進(jìn)度是多少?
int download = FILESIZE - total;
double rate = (download * 1.0 / FILESIZE) * 100.0;
cb(rate);
}
}
int main()
{
download(process_flush);
return 0;
}
3.2 執(zhí)行效果
文章來源:http://www.zghlxwxcb.cn/news/detail-787329.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-787329.html
到了這里,關(guān)于【Linux】編寫第一個(gè)小程序:進(jìn)度條的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!