您的位置:首页 > 运维架构 > Linux

linux下实现简单的进度条

2017-04-04 11:10 197 查看

缓冲区

想要写一个实现进度条的代码,我们就得先明白缓冲机制。

首先看下面这两段代码。

#include<stdio.h>
#include<unistd.h>

int main()
{
printf("Hello,World!\n");
sleep(3);
return 0;
}


#include<stdio.h>
#include<unistd.h>

int main()
{
printf("Hello,World!");
sleep(3);
}


ps:

1、Linux下sleep()函数为让程序睡眠,参数单位默认为秒,包含在”unistd.h”头文件中,Linux下可以通过man 3 sleep来查看。

2、两个函数唯一的不同在于第一个printf里面多了一个\n

可以看到,在主函数中先实现了printf再实现sleep。所以说程序运行起来肯定是先执行printf语句,再执行sleep。

程序运行结果如下,由于是动态效果,这里就不贴图片了。

1、

直接打印Hello,World!,然后程序睡眠3秒,程序结束。

2、

程序先睡眠3秒,然后打印Hello,World,程序结束。

那么问题就来了,为什么会出现这种情况呢,printf肯定是先于sleep运行的,为什么最后才显示出来,这就引出了缓存区的问题,printf在打印时,并不是直接将结果输出到显示器上,而是将结果保存在缓存区。

第一个程序之所以先打印,是因为有一个\n,也就是所谓的换行,因为printf函数是一个行缓冲机制,它遇到\n后就会将缓冲区的内容刷新到显示屏上。

了解了printf函数的行缓冲机制,那么接下来我们就尝试来写一个进度条函数。

进度条实现

#include<stdio.h>
#include<unistd.h>
#include<string.h>  //用到memset函数

void Proc()
{
int rate = 0;
char bar[102];//因为要包含左右两个[],所以数组大小为102
memset(bar,0,102*sizeof(char));//字符串必须以\0结尾,这里我们直接将数组初始值都设为\0
while(rate <= 100)
{
bar[rate] = '#';
printf("[-101s]",bar);//这里的[101s]是将[]置于两端,'-'是进行左对齐
usleep(100000);//因为sleep默认单位为秒,不便于测试,usleep默认单位为微秒
rate++;
}
printf("\n");
}

int main()
{
Proc();
return 0;
}




下面给出运行结果:

这里的光标每次移动,输出为一段一段的



可以看到输出结果是一段一段出现的,那么这时候就需要考虑用到fflush函数了。

fflush():清除读写缓冲区,参数为标准输入\输出流

那么我们接下来将fflush函数加进去



这里光标一直在最左端,输出是连续的



但是这里的进度条明显不完善,我们需要给它加上百分比,还可以加上一个闪动的光标,以便可以知道程序正在加载。

#include<stdio.h>
#include<unistd.h>
#include<string.h>

void Proc()
{
int rate = 0;
char bar[102];
memset(bar,0,102*sizeof(char));
const char* lable="|/-\\"; \\这里注意一下,直接输入一个\会被系统认为是转义,所以要输入\\
while(rate <= 100)
{
bar[rate] = '#';
printf("[-101s] [%d%%] [c%]",bar,rate,lable[rate%4];//这里的%%同上,防止转义。rate%4防止溢出
fflush(stdout);参数为标准输出流
usleep(100000);
rate++;
}
printf("\n");
}

int main()
{
Proc();
return 0;
}


下面是linux下的代码,我将自己的vim进行了简单配置,详情可见上篇文章。



最后给出输出结果:



到这里,一个简单的进度条代码就实现完全了。但是有一个需要注意的地方我得提一下,就是我们的进度条是通过不断刷新递增的‘#’来实现的,而一旦在一行内不能放下你整个进度条的话就会出现下面的情况。



这时候你只需要调整屏幕的分辨率或者缩小字体即可。

这下这个简单的进度条代码算是真的完成了!

在后面的学习中,了解到了shell脚本语言后,觉得用shell脚本写这个代码会比较简单一点。但涉及到了一些shell语法的东西,下面贴出来代码:

实现的思路是一样的。

#!/bin/bash

i=0
bar=''
idx=0
lable={'|' '/' '-' '\\'}
while [ $i -le 100 ]
do
let idx=idx%4
printf "[%-100s][%d%%][\e[43;46;1m%c\e[0m]\r" "$bar" "$i" "$idx" "${lable[idx]}"//这里的[\e[43;46;1m%c\e[0m]是printf语句中的颜色控制
bar=bar+'#'//shell中字符串是可以直接拼接起来的,非常方便
let idx=idx+1
usleep 3000
done
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息