🕺作者: 主页
我的专栏C语言从0到1探秘C++数据结构从0到1探秘Linux菜鸟刷题集
😘欢迎关注:👍点赞🙌收藏✍️留言🏇码字不易,你的👍点赞🙌收藏❤️关注对我真的很重要,有问题可在评论区提出,感谢阅读!!!
前言
前面几章我们讲述了Linux指令、权限管理、编辑器、编译器、软件包管理器、自动化管理工具,也写了简单的”Hello World“程序,但是没有实现过复杂一点的程序,光说不练假把式,今天就带大家来做一个小项目–进度条。
搭建框架
在写代码之前,我们先把文件先建好。
vim main.c
vim process.c
vim process.h
vim makefile
书写代码
在写代码要先讲一个知识点。
1.回车换行
在我们日常使用回车键时,是否注意到,当我们按下回车键,也就是\n
,光标就会换到第二行的开始,其实这里面有两个动作,换行和把光标设置到行开始,在C语言中可用
\r
来把光标换到开始位置
我们来借此写个小demo:倒计时voiddownload(){int cnt=10;while(cnt!=0){printf("%-2d\r",cnt);fflush(stdout); cnt--;sleep(1);}printf("\n");}
效果如下:
第一版
我们最终要实现这个效果:
我们前面讲了
\r
可以把光标移到行始,所以在我们输出缓存字符的时候,每一次都移到一开始的位置,随着缓存字符的增多,来实现进度条的效果。
代码如下:
process.c
#include"process.h"constchar*lable="|/-\\";//通过循环实现一个转动的效果 char bar[NUM];voiddownload(int speed){char bar[NUM];//使用数组来存储”缓存字符“ memset(bar,'\0',sizeof(bar));//初始化 int len =strlen(lable);int cnt=0;while(cnt<=TOP)//设置终止条件 {printf("[%-100s][%d%%][%c]\r", bar, cnt, lable[cnt%len]);//%-100s:预留100个空间左对齐//%%:输出%,也可以使用\%//\r:把光标移到开始位置 fflush(stdout);//清空缓存区
bar[cnt++]=BODY;//将cnt所在位置设置为”BODY" if(cnt<100)bar[cnt]=RIGHT;//设置> usleep(speed);//控制进度条的速度,单位是微秒 }printf("\n");}
main.c
#include"process.h"intmain(){download(100000);return0;}
process.h
#pragmaonce#include<stdio.h>#include<unistd.h>#include<string.h>#defineNUM102#defineTOP100#defineBODY'='#defineRIGHT'>'externvoiddownload(int speed);
makefile
process:process.c main.c
gcc -o $@ $^.PHONY:clean
clean:
rm -f process
通过注释,应该可以清楚明白代码的实现原理,但是进度条该怎么用呢?这是一个问题,下面我们来模拟一下使用场景,只需要再修改一下代码即可。
第二版
参考代码注释理解
main.c
#include"processBar.h"typedefvoid(*callback_t)(int);// 函数指针类型// 模拟一种安装或者下载voiddownLoad(callback_t cb){int total =1000;// 1000MBint curr =0;// 0MBwhile(curr <= total){// 模拟进行着某种下载的任务, 我usleep(50000);// 模拟下载花费的时间int rate = curr*100/total;// 更新进度cb(rate);// 通过回调,展示进度
curr +=10;// 循环下载了一部分}printf("\n");}intmain(){printf("donwnload 1: \n");downLoad(processbar);initbar();printf("donwnload 2: \n");downLoad(processbar);initbar();printf("donwnload 3: \n");downLoad(processbar);initbar();printf("donwnload 4: \n");downLoad(processbar);initbar();return0;}
processBar.h
#pragmaonce#include<stdio.h>#include<unistd.h>#include<string.h>#include<unistd.h>#defineNUM102#defineTOP100#defineBODY'='#defineRIGHT'>'externvoidprocessbar(int rate);externvoidinitbar();
processBar.c
#include"processBar.h"constchar*lable="|/-\\";char bar[NUM];// 是如何被调用的voidprocessbar(int rate){if(rate <0|| rate >100)return;int len =strlen(lable);printf("[%-100s]""[%d%%][%c]\r", bar, rate, lable[rate%len]);// 没有\n,就没有立即刷新,因为显示器模式是行刷新fflush(stdout);
bar[rate++]= BODY;if(rate <100) bar[rate]= RIGHT;}voidinitbar(){memset(bar,'\0',sizeof(bar));}
makefile
processbar:processBar.c main.c
gcc -o$@ $^
.PHONY:clean
clean:
rm-f processbar
效果是一样的,看到这里,我相信你对实现一个进度条已经非常了解了,但是有没有觉得它有点不好看,那么我们再来优化一下。
第三版
怎么修改?这里要了解一下怎么让编译器输出颜色,可参考这篇文章
http://t.csdn.cn/O2T8F
只需修改
processBar.c
文件即可
如下:
#include"processBar.h"constchar*lable="|/-\\";char bar[NUM];// 是如何被调用的voidprocessbar(int rate){if(rate <0|| rate >100)return;int len =strlen(lable);printf("\033[38;2;128;0;128m\033[48;2;255;255;255m[%-100s][%d%%][%c]\033[m\r", bar, rate, lable[rate % len]);fflush(stdout);
bar[rate++]= BODY;if(rate <100) bar[rate]= RIGHT;}voidinitbar(){memset(bar,'\0',sizeof(bar));}
效果如下:
后记
本篇我们讲述了如何在Linux上实现一个进度条,并对其进行了美化,但是我们的目的是通过做项目来把之前所学的相关知识串起来,我并没有对它进行过多的讲解,因为它本身并不难,难的是你在linux系统上编程的过程,但它也是最重要的!
版权归原作者 迷茫的启明星 所有, 如有侵权,请联系我们删除。