在Linux下,我们安装软件时会经常看到进度条,来告知我们安装的进度。我们不妨自己模拟实现一个进度条,看看其中的细节。模拟实现进度条并不困难,但其中的细节我们又不可忽视。本篇文章会对模拟实现进度条进行详解

文章目录

一、进度条整体模板

二、输出缓冲区详解

三、模拟实现进度条思路及代码详解

3、1 回车和换行区别

3、2 模拟实现进度条思路详解

3、2、1 初阶进度条

3、2、2 进阶进度条


‍♂️作者:@Ggggggtm‍♂️

专栏:Linux从入门到精通 、高频面试问题

标题:模拟实现进度条小程序

❣️寄语:与其忙着诉苦,不如低头赶路,奋路前行,终将遇到一番好风景❣️

一、进度条整体模板

谈到进度条,我们首先想到的是一个动态表示进度的显示程序。首先,我们先来看一下进度条整体的模板,也就是我们所要模拟实现的进度条。如下:

模板1:

模板2:

我们看到,上述有两个模板,两个模板大同小异,只是输出格式不同而已。我们似乎已经有了一个大概的整体思路。无非就是格式打印输出嘛。真的是这样吗?确实是这样。但并不只是单纯的输入和输入。其中还涉及到了缓冲区和回车、换行的概念和细节。我们接着往下看。

二、输出缓冲区详解

我们平常使用的printf函数,是输出到屏幕。但是是直接输出到屏幕的吗?我们看下面的例子:

#includeint main(){int i=0;for(i=5;i>=0;i--){printf("%d",i);sleep(1);//睡眠1秒}return 0;}

我们看上述代码,输出结果是什么呢?我们第一反应是每间隔一秒依次输出5、4、3、2、1、0。我们直接看结果:

我们看到并非每间隔一秒依次输出5、4、3、2、1、0。而是过了6秒后直接输出了5、4、3、2、1、0。这是为什么呢?从这例子,我们间接了解到输出并非直接输出到屏幕上。那中间还有什么呢?其实,我们输出是先输出到了缓冲区。缓冲区又分为输入缓冲区输出缓冲区。这里明显的是先输出到了输出缓冲区。

我们再看一个例子:

#includeint main(){int i=0;for(i=5;i>=0;i--){printf("%d\n",i); sleep(1);//睡眠1秒}return 0;}

上面的代码相对于第一个例子,我们多了一个换行。我们再看一下输出结果:

我们看到是每间隔一秒依次输出5、4、3、2、1、0。这又是为什么呢?这就关系到了把输出缓冲区的内容刷新到屏幕上的规则:

  1. 程序正常结束,作为main函数return操作的一部分,缓冲区被刷新。
  2. 当缓冲区的内容满了的时候,缓冲区会自动刷新到屏幕上。
  3. 可以使用操作符endl、fflush和 ends 来显示的刷新缓冲区。这三个都是IO库中的操作符,endl能完成换行和刷新缓冲区的工作。flush只完成刷新缓冲区的工作。而ends会向缓冲区插入一个空字符,然后刷新缓冲区。

了解到了输出缓冲区的刷新规则后,我们对上面的两个例子的输出结果就很容易理解了。当然,我们讲解了这么多输出缓冲区是为什呢?我们先回到模拟实现进度条,我们打印的进度条,是在一行上打印出的,并没有换行。这里就引出了两个问题怎么做到不换行还能不断动态更新打印数据呢怎么及时打印出缓冲区的数据呢?我们接着往下看。

三、模拟实现进度条思路及代码详解

3、1 回车和换行区别

我们上面的问题是:怎么做到不换行还能不断动态更新打印数据呢?首先换行( \ n )是不可以的。这里我们就可以用回车( \ r )啊???换行和回车不一样吗?答案是不一样的

回车 \r 本义是光标重新回到本行开头,r的英文return,控制字符可以写成CR,即Carriage Return。

换行 \n 本义是光标往下一行(不一定到下一行行首,还有可能是接上一行 行末另起一行。),n的英文newline,控制字符可以写成LF,即Line Feed。

但是回车并不能刷新缓冲区。所以我们还要用到fflush(stdout)来刷新缓冲区到屏幕上。我们可结合下面例子一起理解一下:

#include#includeint main(){int i=0;for(i=5;i>=0;i--){printf("%d\r",i);fflush(stdout);sleep(1);}return 0;} 

通过不断的在同一行输出,我们可以得到一个类似倒计时的小程序,具体输出结果如下:

通过上面的例子,我们可以很好的理解回车和换行的区别。同时又解决了上述的两个问题。

3、2 模拟实现进度条思路详解

3、2、1 初阶进度条

首先,我们想到的是进度条完成是达到百分之百。那我们可以定义一个长度为105字符数组,这里多5个位置,是为了防止越界造成不必要的麻烦注意,打印字符串时遇到‘\0’停止)。我们可通过100次循环,不断改变字符数组内容,再同过回车(\r)和格式化输出,我们就可以得到一个初步形式的进度条。我们结合代码一起理解:

#include#include#include#define MAX 105int main(){int i=0;char bar[MAX];memset(bar,0,sizeof(bar)); //初始化字符数组为0while(i<=100){printf("[%-100s][%3d%%] \r",bar,i,); fflush(stdout);bar[i]='#';i++;usleep(50000);}printf("\n");return 0; } 

上面我们可以看到有usleep函数。sleep函数睡眠时间是以秒为级别的。usleep是以微妙级别的。usleep(50000)也就是睡眠0.05秒。循环100次一共是睡眠5秒,也就是我们5秒多一点可以完成打印整个进度条。我们看输出结果:

3、2、2 进阶进度条

我们为了表示进度条在运行,我们可在最后加上一个旋转的字符表示正在运行。怎么加一个旋转的字符呢?我们可创建一个字符数组,存储旋转字符的不同状态。进而通过循环来控制字符旋转。我们可看如下代码:

#include#include#include#define MAX 100int main(){int i=0;char bar[MAX+5];memset(bar,0,sizeof(bar));const char* arr="|\\-/";//旋转字符数组while(i'; //另一种格式 i++;usleep(50000);} printf("\n"); return 0; }

我们直接看输出结果:

最后会有一个动态表示的字符。这样看起来就会比较完整。当然,输出的格式我们可以自己选择。输出的颜色也可通过查询添加到自己的输入格式当中。

以上就是整个用C语言实现的进度条。其中有很多细节还是比较重要的,需要我们重点掌握。希望本篇文章会对你有所帮助,感谢观看ovo~