欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > 【Linux】Linux Progress Pulse-进度条

【Linux】Linux Progress Pulse-进度条

2025/3/10 12:26:16 来源:https://blog.csdn.net/2401_83251330/article/details/146107065  浏览:    关键词:【Linux】Linux Progress Pulse-进度条

 > 🍃 本系列为Linux的内容,如果感兴趣,欢迎订阅🚩

> 🎊个人主页:【小编的个人主页】

>小编将在这里分享学习Linux的心路历程✨和知识分享🔍

>如果本篇文章有问题,还请多多包涵!🙏
>  🎀   🎉欢迎大家点赞👍收藏⭐文章

> ✌️ 🤞 🤟 🤘 🤙 👈 👉 👆 🖕 👇 ☝️ 👍


目录

 🐼前言 

 🐼回车pk换行,缓存区刷新机制

  🐼小demo

 🐼进度条编写


 🐼前言 

我们将使用LInux中基础指令,使用工具vim编写一个进度条程序。通过自已编写的Makefile,使用指令make形成可执行程序,使用指令make clean清理文件

进度条效果演示:

进度条效果演示

 🐼回车pk换行,缓存区刷新机制

 回车换行是一个概念吗?

答案显然不是,回车是指光标回到这一行的初始位置(\r就是回车的转义字符),换行是直接切换到下一行,而不回到这一行的初始位置,而我们平时C语言中使用的"\n"默认是回车+换行

那这有什么用呢?我们来观察一个现象:

首先我们创建一个code.c文件来观察,其内容是:

形成可执行程序

运行结果,我们发现,hello world先被打印到显示屏上,然后过了一秒,程序完成,符合我们的预期。

我们这次不加"\n"试试:

现象:发现,屏幕中先过了一秒,然后最后显示出来hello world

那我们这次只加回车"\r"试试:

现象:发现hello world竟然被吞掉了,什么都不打印,这是为什么????hello world 去哪了??

其实在睡眠期间,hello world在缓存区中,而"\n"作为一种刷新机制,可以直接刷新到显示屏文件中,所以我们看到了hello world。第二种,在程序结束后,将缓存区中的内容拷贝到显示屏文件中,所以我们也能看到,第三种,加了"\r"回车,我们看不到的原因是因为,光标回到这一行的开始位置,程序结束,将光标前的内容刷新,没有内容,所以什么都没有。

总结一下刷新机制:

1:如果\n或者\r\n,会使\n之前的内容,全部刷新到显示器上

2:程序结束,历史数据,会被刷新到显示屏上

那对于第三种情况,如果我们想强行刷新到显示屏上可以使用fflush函数进行刷新(即将缓存区的内容刷新到显示屏中):

修改完再打印一下code.c

此时即是回车,也将内容刷新到显示屏上。

  🐼小demo

那既然有了以上理论,我们可以实现一个简易版的计时器,回车到起始位置,进行刷新覆盖.

#include<stdio.h>
#include<unistd.h>int main()
{int n = 10;while(n){printf("%-2d\r",n);fflush(stdout);n--;sleep(1);}printf("\n");return 0;
}

每次打印完,回车到起始位置,将内容刷新到显示屏上,光标又回到了行开始位置。让我们有了一种计时器倒计时的感觉。回车的目的就是将光标重新回到起始位置。

 🐼进度条编写

 下面我们实现一个进度条,目标有三个:

1:能不断加载进度条

2:能显示百分比

3:加载图标能不能转动,表示加载中~

下面我们先根据以上要求实现一个简易版:

我们通过"process.h","process.c","main.c"三个文件进行实现:

让我们的进度条先跑起来:

"process.c"逻辑

#include"process.h"
#define LENGTH 101
#define LABLE '#'void process()
{//定义缓存区static char bar[LENGTH];memset(bar,0,sizeof(bar));//定义光标const static char* str = "/|\\-";int len = strlen(str);int cnt = 0;while(cnt<LENGTH){printf("[%-100s][%d%%][%c]\r",bar,cnt,str[cnt%len]);fflush(stdout);bar[cnt++] = LABLE;usleep(20000);}printf("\n");
}

我们通过让cnt不断增长,我们默认进度条的长度最多为100字'#',直到填充满,每次填充,我们都进行刷新,并让光标回到初始位置,为下一次刷新做准备,加载图标通过通过取模运算每次更新。

verson1进度条演示:

verson1

可是,这样,是不符合实际情况的。原因:

我们的下载速度都是与下载包大小和网速有关的,所以进度条增加速度我们需要关心。

即进度条不能直接更新完,要根据具体进度进行刷新

我们更新一下下载逻辑:

通过下载安装包和下载速度实时更新,下载一次每次都刷新进度条,只要没下载完,就一直下载。

"main.c"

#include"process.h"
//直接替换
#define  TOTAL 1024.0
#define  SPEED 1.0//检查对比一次,并加几组,看看下载速度和网速
void DownLoad(double total,double speed)
{double current = 0;while(current<=total){FlushProcess(current,total);usleep(2200);current+=speed;}
}
int main()
{printf("下载中\n");DownLoad(TOTAL,SPEED);DownLoad(1024.0,1.0);DownLoad(512.0,2.0);DownLoad(800.0,4.0);DownLoad(2000.0,2.0);DownLoad(10240.0,10.0);printf("下载完成>^o<^\n");return 0 ;
}

"process.c"

#include"process.h"
#define LENGTH 101
#define LABLE '#'void FlushProcess(double current,double target)
{//更新出当前进度double rate = (current/target)*100.0;//200-1000//整数个进度递增,刷新一个#int cnt = (int)rate;//定义光标const static char* sysb = "/|\\-";int len = strlen(sysb);static int index = 0;//缓存区static char bar[LENGTH];memset(bar,0,sizeof(bar));for(int i=0;i<cnt;i++){bar[i] = LABLE;}printf("[%-100s][%.1lf%%][%c]\r",bar,rate,sysb[index++]);fflush(stdout);index%=len;if(rate>=100.0) printf("\n");fflush(stdout);
}

"process.h"

#include<stdio.h>
#include<unistd.h>
#include<string.h>
void FlushProcess(double current,double target);

最后,看一下我们做出来的效果:

verson2:

   感谢你耐心地阅读到这里,你的支持是我不断前行的最大动力。如果你觉得这篇文章对你有所启发,哪怕只是一点点,那就请不吝点赞👍,收藏⭐️,关注🚩吧!你的每一个点赞都是对我最大的鼓励,每一次收藏都是对我努力的认可,每一次关注都是对我持续创作的鞭策。希望我的文字能为你带来更多的价值,也希望我们能在这个充满知识与灵感的旅程中,共同成长,一起进步。如果本篇文章有错误,还请大佬多多指正,再次感谢你的陪伴,期待与你在未来的文章中再次相遇!⛅️🌈 ☀️   

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词