Linux | 手把手教你写一个进度条小程序-2

简介: Linux | 手把手教你写一个进度条小程序

五、进度条小程序【详解】

好,终于来到了我们心心念念的【进度条】了,有关我为什么要将前面的这些知识做铺垫,你看完本模块就知道了:smile:

1、准备工作

  • 既然是个小程序,那我们就用工程的形式来编写,那就是使用【多文件】的形式。首先要创建一个【proc】的目录其中包含
  • 一个头文件proc.h
  • 一个源文件proc.c
  • 一个主调文件main.c
  • 这里充分的利用到了之前所学习的【vim】来进行多文件编写如下图所示👇

image.png

  • 因为我们要对代码去进行编译,每次去重新编译会很冗杂,因此可以使用之前学过【make/Makefile】进行自动化构建
  • 先前有说到过,目标文件它所依赖的是一个文件列表,不仅仅可以是一个,也可以是多个,例如这里的【main.c】与【proc.c】,因此在使用gcc进行编译的时候就需要对这两个.c的文件一起进行编译

image.png

  • 那此时就有同学会问,不是还有一个proc.h吗?为何不进行一起编译呢?
  • 这一点我之前在讲解【gcc】的时候也有提到过,我们在进行多文件编译时候是不需要考虑【头文件】的,因为在预处理阶段头文件就会在它被包含的.c源文件中进行展开,因此我们加了和没加一样,你想加的话也可以加上,不会有问题,不过一般我们是不加的

2、进度条样式说明

准备工作做好之后,我们来看看需要实现的进度条需要是一个什么样子

  • 首先主体部分很明确,需要一个很大的空行,使用[ ]进行囊括,中间用==>这样的符号进行一个慢慢地推进
  • 那既然是进度条,就一定有进度,一般使用百分比来进行显示,即50%
  • 除了上面两个,我们还需要这个进度条有缓冲显示,也就是我们日常在Windows下看到的那种转圈圈的缓冲,不过呢,我们是在Linux环境下,无法做到这种图形化界面,但是我们可以使用旋转字符来进行一个模拟[|][/][-][\]


这就是进度条的大致形状,要先有个数 [=======================>][100%][/]

3、主体进度推进实现【重点】

首先要实现的是主体进度条的推进时间,先简单地实现一下这个进度条不断变长的过程(๑•̀ㅂ•́)و✧

下面是详细介绍,想直接看整体代码的可以拉到最后面

  • 我们可以将整体进度条看作是一个字符串,现在要实现从0% ~ 100%的进度条扩展,因此就需要一个长度为101的字符数组,这里首先使用#define进行一个宏定义
#define SIZE 101
  • 这里最令你困惑的应该是这个memset,为什么要使用它呢?因为我相当于是使用一个循环的方式,每次都去修改这个字符数组当前位置上的字符,将其变为=,然后每次去打印的时候下一个位置就会多出来一个=,此时在视觉上看其实就相当于是一个进度条在慢慢推进的样子:open_mouth:,不过在最后不要忘记带上sleep()这个睡眠函数,让进度条每过一秒钟向后前进一个单位
memset(bar, '\0', sizeof(bar));
//初始化整个bar字符串均为\0,sizeof(数组名)表示取到这个数组的字节大小
  • 对于字符串我们知道自身就带有\0,因此我们每次在添加完当前位置的=后,还要在其后面添加上一个\0才行,这会显得很麻烦,于是我就想到了在一开始就将整个字符串的内容初始化为\0,对于sizeof(bar)来说也就是sizeof(数组名),可以取到这个数组的整个字节大小,若是不懂的可以看看C语言数组章节

下面是代码

  1 #include "proc.h"
  2 
  3 #define SIZE 101
  4 
  5 void progress()
  6 {
  7     char bar[SIZE];
  8     memset(bar, '\0', sizeof(bar));
  9     //初始化整个bar字符串均为\0,sizeof(数组名)表示取到这个数组的字节大小
 10 
 11     int i = 0;
 12     while(i <= 100)                                                                                              
 13     {
 14         printf("[%s]\n", bar);
 15         bar[i] = '=';
 16         i++;
 17         sleep(1);
 18     }
 19 }

然后来看一下上面这段代码的演示过程

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/79bd4943d2714c439d731e536374ef3d~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp

  • 很明显可以看出,我们想要的进度条并不是这样的,虽然它有在进行一个慢慢的推进,但是我们想要它只在一行进行一个推进,此时应该要想到将最后打印的换行符\n去掉,让光标每次回到行首,再打印这个字符串
printf("[%s]\r", bar); 

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ed0dd359ac5f40e78f03b5eb421c5552~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp

不过可以看到,并没有显示出任何东西,此时相信你一定可以回答出来了,那就是:==缓冲区没刷新!==

fflush(stdout);
  • 可以看到,因为每次都提前刷新了缓冲区,所以要打印的内容被显示出来了,因为sleep(1)每次睡眠一秒,使得进度条一个不断推进的效果

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2f2f1bca7a0145369ba7df6c76264d08~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp

不过可以观察到这个进度条推进得很慢,那有没有办法使它快一点呢❓

  • 此时我们可以到Linux中的另一个睡眠延时函数usleep(),我们可以通过【man】命令来查看一下它对应的手册
  • 通过和sleep()函数进行对比可以发现它的单位不是【秒】,而是【微秒】,对应单位转换也就是10^6^秒

image.pngimage.png

  • 此时我们就可以对睡眠函数去进行一个修改,10^6^是1秒,那么10^5^就是0.1秒
//sleep(1);      1秒
// usleep(1000000);  1秒                                                                                  
usleep(100000);  //0.1秒

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d78f7759ba7b4be2a34344f2f2b66256~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp

  • 上面有说到过,对于主体的进度条是需要预留出一个100的空间,好呈现进度条从0 ~ 100的推进,就可以上面说到过的格式化占位符
printf("[%100s]\r", bar);

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/889847a7bd924d5d8044374289dce4d1~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp

  • 不过可以看到,加上之后是从右向左进行了一个推进,这不符合我们的认识,应该是从右向左才对,此时可以这样写,在100前面加个-
printf("[%-100s]\r", bar);

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1834f148d26d4c538a9c42e5dc277249~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp

  • 这么长的进度条,应该看了很烦把,把它改小,一样保持0% ~ 100%

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d6f880ed58914775a66f8f68c88b4d53~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp

  • 改动的部分多一些,给出代码,主要是循环的条件、字符数组预留空间以及占位符
  1 #include "proc.h"
  2 
  3 #define SIZE 51
  4 
  5 void progress()
  6 {
  7     char bar[SIZE];
  8     memset(bar, '\0', sizeof(bar));
  9     //初始化整个bar字符串均为\0,sizeof(数组名)表示取到这个数组的字节大小
 10 
 11     int i = 0;
 12     while(i <= 50)
 13     {
 14         printf("[%-50s]\r", bar);                                                                                
 15         bar[i++] = '=';
 16         fflush(stdout);
 17        // usleep(1000000);  1秒
 18         usleep(100000); //0.1秒
 19     }
 20     printf("\n");
 21 }
  • 为了看出让被人看出这是一个进度条的样子,在后面追加一个>。重新定义一下
#define STYLE '='  
#define ARR '>'  
  • 为了使进度条在99%之前最后一个字符呈现【>】,而最后到100%为【=】,我们此处就需要再循环内部做一个判断若是其i != 50,就一直追加【>】,最后到达100%时便为【=】
  • 那便需要预留出52个位置的空间
#define SIZE 52
if(i != 50) bar[i] = ARR;  

此时来看的话我们进度条的主体部分就做完了

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/efb3770907bc4f11853e682cc9fd9de2~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp

4、百分比递增实现

接下去我们来实现一下百分比递增这块

  • 若是一开始很长的进度条,循环次数为101次的话直接输出下标i即可,但是我们修改了进度条的长度,所以需要使用i * 2,也可以实现一个0% ~ 100%的过程
printf("[%-50s][%d]\r", bar, i * 2);

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6de7cbfae4774c61af5453445e34be56~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp

  • 来给数字的后面加上一个【%】,不过可以看到,编译器不允许我们这样做,这点要涉及到.bat中的批处理程序,此时我们需要写上【%%】才算是一个【%】,你也可以理解为我们在写文件路径时的【\】当做【\】,防止出现转义字符的歧义
  • 如果想了解可以看看这个文章——> 链接

image.png

printf("[%-50s][%d%%]\r", bar, i * 2);

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f4aaa1ab32b8434680df672589351956~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp

5、旋转字符轮回实现

接下去来实现最后的一个旋转字符的轮回,已到达图形化界面中的缓冲功能

  • 这一块我们只需要定义一个字符数组,前面加上const是防止里面的内容被修改。而最后一个\\也就是我上面说到的【转义字符歧义】,其实它就是【\】
const char* label = "|/-\\";
  • 然后我们在打印的时候,要去实现一个轮回就需要用到一个取余%的操作,每次打印的都是【0 ~ 3】的倍数
printf("[%-50s][%d%%][%c]\r", bar, i * 2, label[i % 4]);

最后,就实现了一个完整的进度条

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e2a84a7b068048fa8999c07f0aa45813~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp

6、整体代码展示

  1 #include "proc.h"
  2 
  3 #define SIZE 52
  4 #define STYLE '='
  5 #define ARR '>'
  6 
  7 void progress()
  8 {
  9     const char* label = "|/-\\";
 10    // printf("%c\n", label[0]);
 11     char bar[SIZE];
 12     memset(bar, '\0', sizeof(bar));
 13     //初始化整个bar字符串均为\0,sizeof(数组名)表示取到这个数组的字节大小
 14 
 15     int i = 0;
 16     while(i <= 50)
 17     {
 18         printf("[%-50s][%d%%][%c]\r", bar, i * 2, label[i % 4]);                                                 
 19         bar[i++] = STYLE;
 20         if(i != 50) bar[i] = ARR;
 21         fflush(stdout);
 22        // usleep(1000000);  1秒
 23         usleep(100000); //0.1秒
 24     }
 25     printf("\n");
 26 }

六、总结与提炼

好,我们来总结一下本文所学习的内容

  • 为了学习进度条小程序的编写,我们首先学习学习了C语言中的两个控制字符【\n】与【\r】,知道了它们分别有什么作用
  • 这它们的基础上,又了解到了计算机内部存在缓冲区这么一个概念,知道了缓冲区需要被刷新才可以显示。通过观察5个代码段对这些概念也有了更加深刻的理解
  • 学习了上面两个小知识后,里面通过所学实现了一个【倒计时】的功能,做到了活学活用
  • 最后的舞台给到【进度条】,我们分别通过三个主要模块实现了进度条,包括:进度条的主体部分、进度条的百分比递增以及旋转字符模拟缓冲图形。有关进度条,你学会了吗:stuck_out_tongue_winking_eye:

以上就是本文所要阐述的所有内容,感谢您的阅读:rose:

相关文章
|
7月前
|
小程序 Linux 开发工具
【Linux】Linux 开发工具(vim、gcc/g++、make/Makefile)+【小程序:进度条】-- 详解
【Linux】Linux 开发工具(vim、gcc/g++、make/Makefile)+【小程序:进度条】-- 详解
|
4月前
|
Linux 开发工具
linux下使用gcp拷贝数据的时候显示进度条
linux下使用gcp拷贝数据的时候显示进度条
31 2
|
5月前
|
小程序
【亲测有效】支持横竖屏 微信小程序video禁止进度条拖动,微信小程序遮罩进度条,
【亲测有效】支持横竖屏 微信小程序video禁止进度条拖动,微信小程序遮罩进度条,
87 1
【亲测有效】支持横竖屏 微信小程序video禁止进度条拖动,微信小程序遮罩进度条,
|
6月前
|
小程序 Linux C语言
Linux小程序 —— 进度条
Linux小程序 —— 进度条
96 6
|
6月前
|
Linux
【make/Makefile】Linux下进度条的设计与实现
【make/Makefile】Linux下进度条的设计与实现
|
7月前
|
数据可视化 小程序 Linux
【Linux】6. 实现进度条和git基本认识和使用
【Linux】6. 实现进度条和git基本认识和使用
62 4
|
2月前
|
移动开发 小程序 数据可视化
基于npm CLI脚手架的uniapp项目创建、运行与打包全攻略(微信小程序、H5、APP全覆盖)
基于npm CLI脚手架的uniapp项目创建、运行与打包全攻略(微信小程序、H5、APP全覆盖)
292 3
|
2月前
|
小程序 API
微信小程序更新提醒uniapp
在小程序开发中,版本更新至关重要。本方案利用 `uni-app` 的 `uni.getUpdateManager()` API 在启动时检测版本更新,提示用户并提供立即更新选项,自动下载更新内容,并在更新完成后重启小程序以应用新版本。适用于微信小程序,确保用户始终使用最新版本。以下是实现步骤: ### 实现步骤 1. **创建更新方法**:在 `App.vue` 中创建 `updateApp` 方法用于检查小程序是否有新版本。 2. **测试**:添加编译模式并选择成功状态进行模拟测试。
53 0
微信小程序更新提醒uniapp
|
4月前
|
小程序 前端开发 Java
SpringBoot+uniapp+uview打造H5+小程序+APP入门学习的聊天小项目
JavaDog Chat v1.0.0 是一款基于 SpringBoot、MybatisPlus 和 uniapp 的简易聊天软件,兼容 H5、小程序和 APP,提供丰富的注释和简洁代码,适合初学者。主要功能包括登录注册、消息发送、好友管理及群组交流。
114 0
SpringBoot+uniapp+uview打造H5+小程序+APP入门学习的聊天小项目
|
4月前
|
小程序 前端开发 JavaScript
【项目实战】SpringBoot+uniapp+uview2打造一个企业黑红名单吐槽小程序
【避坑宝】是一款企业黑红名单吐槽小程序,旨在帮助打工人群体辨别企业优劣。该平台采用SpringBoot+MybatisPlus+uniapp+uview2等技术栈构建,具备丰富的注释与简洁的代码结构,非常适合实战练习与学习。通过小程序搜索“避坑宝”即可体验。
112 0
【项目实战】SpringBoot+uniapp+uview2打造一个企业黑红名单吐槽小程序