襄阳市住房和城乡建设局网站,东莞教育建站,dedecms购物网站,专业做网站哪家便宜这篇博客要综合利用以前的知识#xff0c;来实现一个进度条程序~ 目录
换行回车
缓冲区
实现简单的倒计时
实现进度条
version1
version2 在开始写这个小程序之前#xff0c;我们先学习一些预备知识#xff1a;
换行回车 缓冲区 在我们运行这个程序时… 这篇博客要综合利用以前的知识来实现一个进度条程序~ 目录
换行回车
缓冲区
实现简单的倒计时
实现进度条
version1
version2 在开始写这个小程序之前我们先学习一些预备知识
换行回车 缓冲区 在我们运行这个程序时并没有直接打印出“hello bit,hello world...”而是当程序运行结束后才显示出来但是这并不代表这句打印没有执行而是没有显示出来而已。
那么在我sleep期间字符串在哪里
答案就是被保存在叫做缓冲区的地方就是一块内存空间当程序结束时一般会自动刷新缓冲区到字符设备显示器另外如果程序遇到‘\n’的时候也会刷新缓冲区。如果想要强制刷新可以使用fflush命令。 那么为什么要有缓冲区呢为什么按行刷新为了提高效率方便人类阅读人类读信息都是按行读的是一种尊重用户的表现。 实现简单的倒计时
在实现倒计时中我们想要达到的效果是依次显示数字并且下一个覆盖前一个数字创建test.c文件 1 #include stdio.h2 #include unistd.h3 4 int main()5 {6 int cnt10;7 while(cnt 0)8 {9 printf(倒计时:%2d\r,cnt); 10 fflush(stdout);11 cnt--;12 sleep(1);13 }14 printf(\n);15 16 return 0 ;17 }
我们实现的效果是10,9...10的倒计时效果其中
printf(倒计时:%2d\r,cnt);
这句代码中\r是回车在一次打印完成后光标回到最前面继续打印下一个值覆盖掉上一次的值用%2d的格式打印的原因是每次打印两个字符以防某个字符一直在屏幕上显示。使用fflush(stdout)强制刷新到显示器上。
此外我们还写了makefile自动化构建工具 mycode:test.c2 gcc -o $ $^3 .PHONY:clean4 clean:5 rm -f mycode
至此完成了简单的倒计时效果。
实现进度条
version1
在实现进度条中我们要创建三个文件Processbar.hProcessbar.cMain.cMain.c负责将Processbar.h中的方法进行调用最终想达到的效果如下图 在Processbar.h中我们定义了Process函数声明;
#pragma once
#include stdio.h
extern void Process();在Processbar.c中实现了Process #include Processbar.h#include string.h#include unistd.h#define Length 101#define Style #const char * label |/-\\;// version1void 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数组来实现进度条大小Length设为101包括最后的‘\0’进度条符号为‘#’。[%-100s]表示字符串靠左对齐保证了‘#’从左边往右增长。通过循环遍历label所指向的数组来实现旋转光标的效果。
需要注意的是因为每次使用‘\r’来实现覆盖的效果但是‘\r’不能让每次结果刷新到显示器上需要用fflush(stdout)来刷新。usleep()函数的单位是微秒包含unistd.h头文件。
在Main.c中调用Process.h
#include Processbar.h
int main() { Process(); return 0;
}
最终的实现效果 version2
上面我们单独写了一个进度条程序但是进度条会单独出现吗肯定不会它要和具体的场景结合。
假设我们要完成一个下载的场景下载指定大小的文件
在Main.c中我们写出download()这样一个函数 double bandwidth 1024*1024*1.0; //downloadvoid 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);//从网络中获取current bandwidth;usleep(10000);}printf(\ndownload done,filesize:%lf\n,filesize);}
其中bandwidth是我们假设的带宽可以理解为下载速度download函数的filesize参数是我们要下载的文件大小第二个参数是进度条打印函数callback_t是函数指针其定义在Processbar.h中
typedef void(*callback_t)(double,double);
在while循环中根据filesize和current的大小打印出当前下载进度的进度条打印完成后继续下载current继续增加然后再打印下一次的进度条并覆盖之前的进度条。
在Processbar.h中有如下声明
#pragma once
#include stdio.h
typedef void(*callback_t)(double,double);
void Process(double total,double current);在Processbar.c中定义了Process函数
//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); }
根据总文件大小total和当前已下载大小current打印出当前的进度条例如当total100、current36时会打印出如下内容 在Main.c中将Process函数作为实参传给download()函数完成下载。
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;
}模拟下载了多个文件其效果如下