1. 准备知识
1.1 简单认识几个函数
1.1.1 sleep()
- unsigned int sleep(unsigned seconds);
复制代码
- 作用:让步伐休眠指定秒数,如:sleep(3); //让步伐休眠3秒
- 与 Windows 上的 Sleep() 函数差异
- 必要包含头文件<unistd.h>
1.1.2 fflush()
- int fflush(FILE* stream);
复制代码
- 作用:刷新缓冲区
- 必要传入一个流
- 必要包含头文件<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 指向的内存块的前 num 个字节设置为指定的 value 值
- 返回设置后的 ptr
- 必要包含头文件<string.h>
1.2 缓冲区
直接上代码观察现象
- #include <stdio.h>
- #include <unistd.h>
- int main()
- {
- printf("you can see me ");
- sleep(3);
- return 0;
- }
复制代码 执行结果图
- 首先要否定上面不切现实的想法,C语言是顺序执行的,以是 printf 函数一定先于 sleep 函数执行。
- 那为什么 3 秒后才打印到屏幕上呢?当然是因为缓冲区!
- printf 函数跑完后,输出的字符串是被保存到 C 对 IO 函数提供的一个缓冲区里了,在步伐退出的时候,缓冲区中的内容才被刷新到屏幕上。
- 我们必要使用上面讲的 fflush 函数把缓冲区中的内容提前强制刷新到屏幕上,使用方法:fflush(stdout);
1.3 回车与换行
首先我要抛出一个概念:回车和换行是不一样的!
- 以是理论上来讲,‘\n’ 和 ‘\r’ 一起用才是我们明确中的”回车“,即:把光标放到下一行最开始的位置。
2. 编写入门版的进度条
2.1 根本逻辑
- 进度 1% 打印 1 个字符,回车到开始的位置,刷新缓冲区;
- 进度 2% 打印 2 个字符,回车到开始的位置,刷新缓冲区;
- …
- 进度 100% 打印 100 个字符,回车到开始的位置,刷新缓冲区,步伐停止。
2.2 美化结果
- 进度条主体增长箭头显示
- 显示进度百分比
- 添加一个动态的旋转光标
2.3 代码实现
- // 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 执行结果
3. 编写升级版的进度条
- 上面的进度条算是一个进度条吗?我们的进度条似乎在一个人玩单机呀,这样的进度条是没有意义的。
- 进度条的进度应该是依靠于其他应用的,比如下载。
- 下面我们模仿一个下载情况,并修改进度条,使进度条可以根据下载的进度,同步举行显示进度的工作。
3.1 代码实现
- // processbar.h
- #pragma once
- #include <stdio.h>
- #define NUM 103
- #define Body '='
- #define Head '>'
- typedef void (*callback_t)(double); // 函数指针类型
- // version 2
- void process_flush(double rate);
复制代码- // processbar.c
- #include "processbar.h"
- #include <string.h>
- #include <unistd.h>
- const char* lable = "|/-\";
- // version 2: 进度是多少,你进度条能知道吗?另外,什么进度?依附于其他应用的,比如下载
- 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)
- // 模拟一种场景,表示一种下载任务
- void download(callback_t cb) // 回调函数的形式
- {
- srand(time(NULL) ^ 1023); // 这样写只是为了让随机数更随机
- int total = FILESIZE;
- while (total)
- {
- usleep(10000); // 下载动作
- int one = rand() % (1024 * 1024); // 一次下载的大小
- total -= one;
- if (total < 0)
- {
- total = 0;
- }
- // 当前的进度是多少?
- int download = FILESIZE - total;
- double rate = (download * 1.0 / FILESIZE) * 100.0;
- cb(rate);
- }
- }
- int main()
- {
- download(process_flush);
- return 0;
- }
复制代码 3.2 执行结果
END
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |