文章目录
1. 预备知识
1.1 简单认识几个函数
1.1.1 sleep()
unsignedintsleep(unsigned seconds);
- 作用:让程序休眠指定秒数,如:
sleep(3); //让程序休眠3秒
- 与 Windows 上的 Sleep() 函数不同
- 需要包含头文件
<unistd.h>
1.1.2 fflush()
intfflush(FILE* stream);
- 作用:刷新缓冲区
- 需要传入一个流
- 需要包含头文件
<stdio.h>
1.1.3 usleep()
intusleep(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>intmain(){printf("you can see me ");sleep(3);return0;}
执行效果图
- 首先要否定上面不切实际的想法,C语言是顺序执行的,所以 printf 函数一定先于 sleep 函数执行。
- 那为什么 3 秒后才打印到屏幕上呢?当然是因为缓冲区!
- printf 函数跑完后,输出的字符串是被保存到 C 对 IO 函数提供的一个缓冲区里了,在程序退出的时候,缓冲区中的内容才被刷新到屏幕上。
- 我们需要使用上面讲的 fflush 函数把缓冲区中的内容提前强制刷新到屏幕上,使用方法:
fflush(stdout);
1.3 回车与换行
首先我要抛出一个概念:回车和换行是不一样的!
- 回车( \r ):把光标放到当前行的开始。
- 换行( \n ):把光标放到当前位置的下一行。
- 所以理论上来讲,‘\n’ 和 ‘\r’ 一起用才是我们理解中的”回车“,即:把光标放到下一行最开始的位置。
2. 编写入门版的进度条
2.1 基本逻辑
- 进度 1% 打印 1 个字符,回车到开始的位置,刷新缓冲区;
- 进度 2% 打印 2 个字符,回车到开始的位置,刷新缓冲区;
- …
- 进度 100% 打印 100 个字符,回车到开始的位置,刷新缓冲区,程序终止。
2.2 美化效果
- 进度条主体增加箭头显示
- 显示进度百分比
- 添加一个动态的旋转光标
2.3 代码实现
// porcessbar.h#pragmaonce#include<stdio.h>#defineNUM103#defineBody'='#defineHead'>'// version 1voidprocess();
// processbar.c#include"processbar.h"#include<string.h>#include<unistd.h>constchar* lable ="|/-\\";// version 1voidprocess(){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#pragmaonce#include<stdio.h>#defineNUM103#defineBody'='#defineHead'>'typedefvoid(*callback_t)(double);// 函数指针类型// version 2voidprocess_flush(double rate);
// processbar.c#include"processbar.h"#include<string.h>#include<unistd.h>constchar* lable ="|/-\\";// version 2: 进度是多少,你进度条能知道吗?另外,什么进度?依附于其他应用的,比如下载char buffer[NUM]={0};voidprocess_flush(double rate){staticint 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>// 模拟文件大小#defineFILESIZE(1024*1024*1024)// 模拟一种场景,表示一种下载任务voiddownload(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);}}intmain(){download(process_flush);return0;}
3.2 执行效果
END
本文转载自: https://blog.csdn.net/m0_73156359/article/details/135515275
版权归原作者 字节连结 所有, 如有侵权,请联系我们删除。
版权归原作者 字节连结 所有, 如有侵权,请联系我们删除。