引言
模拟实现Linux中的进度条
一、前置知识
回车换行是两个动作:\n = \r + \n
运行这段代码会发现,打印会在sleep3秒后进行,为什么是这样的呢?
1 #include<stdio.h>
2 #include<unistd.h>
3
4
5 int main()
6 {
7 printf("hello word");
8 sleep(3);
9 return 0;
10 }
因为打印函数的内容在缓冲区里面(在内存里面),需要刷新一下屏幕的缓冲区才可以显示出来。
当加上\n时,就可以先打印后sleep3秒。说明屏幕缓冲区的内容是按行刷新的。
所以可以用fflush函数来手动刷新缓冲区:
1 #include<stdio.h>
2 #include<unistd.h>
3
4
5 int main()
6 {
7 printf("hello word");
8 fflush(stdout);
9 sleep(3);
10 return 0;
11 }
二、先实现一个倒计时程序
1 #include<stdio.h>
2 #include<unistd.h>
3
4
5
6
7 int main()
8 {
9 int i = 10;
10 for(; i >= 0; i--)
11 {
12 printf("clock:%2d\r",i);
13 fflush(stdout);
14 sleep(1);
15 }
16 printf("\n");
17
18 return 0;
19 }
主要是掌握一下对上面知识的运用。
三、模拟实现进度条
版本1:
process.c文件中:
1 #include"process.h"
2 #include<unistd.h>
3 #include<string.h>
4
5 #define SIZE 101
6 #define STYLE '='
7
8
9 void Process()
10 {
11 const char* lable = "|/-\\";
12 int len = strlen(lable);
13 char processbuff[SIZE];
14 memset(processbuff, '\0', sizeof(processbuff));
15
16 int cnt = 0;
17 while(cnt <= 100)
18 {
19 printf("[%-100s] [%d%%][%c]\r", processbuff, cnt, lable[cnt%len]);
20 fflush(stdout);
21 processbuff[cnt++] = STYLE;
22 usleep(30000);
23 }
24 printf("\n");
25
26
27 }
很显然,版本1只是简单模拟了一下进度条,非常不实际,所以实现一个版本2
版本2:
process.h文件中:
1 #pragma once
2 #include<stdio.h>
3
4 void Process();
5 void FlushProcess(double total, double curr); //更新进度,按照下载进度,更新进度条
6
process.c文件中:
1 #include"process.h"
2 #include<unistd.h>
3 #include<string.h>
4
5 #define SIZE 101
6 #define STYLE '='
7
8
9 void FlushProcess(double total, double curr) //更新进度,按照下载进度,更新进度条
10 {
11 if(curr > total)
12 curr = total;
13 double rate = curr / total * 100;
14 int cnt = (int)rate;
15 char processbuff[SIZE];
16 memset(processbuff, '\0', sizeof(processbuff));
17 int i = 0;
18 for(;i < cnt; i++)
19 {
20 processbuff[i] = STYLE;
21 }
22
23 static const char *lable = "|/-\\";
24 static int index = 0;
25
26 printf("[%-100s][%.1lf%%][%c]\r", processbuff, rate, lable[index++]);
27 index %= strlen(lable);
28 fflush(stdout);
29 if(curr >= total)
30 {
31 printf("\n");
32 }
33
34
35
36 }
main.c文件中:
1 #include<stdio.h>
2 #include"process.h"
3 #include<time.h>
4 #include<stdlib.h>
5 #include<unistd.h>
6
7 double gtotal = 1024.0;
8 double speed = 1.0;
9
10 typedef void (*callback_t)(double, double);
11
12 double SpeedFloat(double start, double range) //模拟不同的速度
13 {
14 int int_range = (int)range;
15 return start + rand()%int_range + (range - int_range);
16 }
17
18 void Download(int total, callback_t cb ) //模拟下载
19 {
20 srand(time(NULL));
21 double curr = 0;
22 while(1)
23 {
24 if(curr > total)
25 {
26 curr = total; //模拟下载完成
27 cb(total, curr); //更新进度,按照下载进度,进行更新进度条
28 break;
29 }
30 cb(total, curr);
31 curr += SpeedFloat(speed, 20.3); //模拟下载行为
32 usleep(30000);
33 }
34 }
35
36
37
38 int main()
39 {
40 printf("download: 20.0MB\n");
41 Download(20.0, FlushProcess);
42 printf("download: 2000.0MB\n");
43 Download(2000.0, FlushProcess);
44 printf("download: 100.0MB\n");
45 Download(100.0, FlushProcess);
46 printf("download: 20000.0MB\n");
47 Download(20000.0, FlushProcess);
48
49 return 0;
50 }
运行结果: