【Linux】-第一个小程序(进度条)

💖作者:小树苗渴望变成参天大树
🎉作者宣言:认真写好每一篇博客
🎊作者gitee:gitee
💞作者专栏:C语言,数据结构初阶,Linux,C++ 动态规划算法
在这里插入图片描述

如 果 你 喜 欢 作 者 的 文 章 ,就 给 作 者 点 点 关 注 吧!

文章目录

  • 前言
  • 一、知识铺垫
    • 1.1回车换行
    • 1.2行缓冲区
    • 1.3倒计时
  • 二、进度条
    • 2.1基础进度条
    • 2.2进阶进度条
  • 三、总结


前言

大家好久不见,已经快一个月没有更新Linux相关的知识了,希望大家还没有忘记前面学过的知识,不记得可以看看我前面写的博客,可以快速帮大家进行回忆,今天我们讲讲一个新的知识,把我们前面说到的make进行联系起来,再讲小程序进度条之前,我还有两个知识铺垫,不然大家不好理解,话不多说,我们开始进入正文


一、知识铺垫

再讲解进度条之前,我们必须了解这两个概念,一个是回车换行,一个是行缓冲区

1.1回车换行

对于回车换行其实是两个概念,一个是回车,一个是换行,换行是光标换到下一行,并不会到文本的开头,回车使光标回到当前行的开始,那在我们语言的层面是怎么做到对文本进行换行和回车的,我们平时说到 \n其实就是换行的意思的,但是语言的本身把他解释成回车换行,\r是回车的意思的,回车换行其实就是先换行再进行回车,我们来看看老式的键盘
加粗样式
这个标志就很形象,为什么要讲解这个知识点,原因是为了更好的引出下面这个要铺垫的知识点

1.2行缓冲区

再我们的C语言中,我们要行缓冲区,这是个什么,为什么要有这个,再我们运行程序的时候,我们会在屏幕上看到显示的内容,这些都是由字符组成的,那我们的C语言不是一个字符一个字符的显示再屏幕上,这样觉得消耗太大了,所以我们有了行缓冲区的概念,就是程序运行时的一块内存,把数据先放到这个内存里面,等到这个小内存满了,就直接一起全部给刷新出来,为什么又叫行缓冲区,就是当一行满了,就一起刷新出来,只有遇到\n或者scanf或者fflush这样的函数就会提前进行刷新,程序结束后,最终也会将数据进行刷新出来。

所以我们来看一个例子:

#include <stdio.h>
#include<unistd.h>
int main()
{printf("hello Makefile!\n");sleep(3);return 0;
}

在这里插入图片描述
再来看这个代码:

#include <stdio.h>
#include<unistd.h>
int main()
{printf("hello Makefile!");//1sleep(3);//2return 0;
}

在这里插入图片描述
大家看到这个结果大概率会认为先执行了2代码,再执行1代码,但是事实却不是这个样子的,我们C语言的代码都是自上往下进行执行的,除非遇到跳转,循环之类的,对于上面的代码的肯定是先执行的打印函数,再执行休眠函数,那为什么不是先打印出来呢??原因就是,打印的数据再缓冲区里面,然后开始执行了2代码,最后程序结束了,就会一起刷新出来,最后从显示出来。

我们想必须提前刷新出来,还有一种方法就是使用fflush函数,我们查看一下手册在这里插入图片描述
再我们c语言会默认打开三个流,这个再C语言专栏的文件操作讲过,一个是输入流stdin,一个是输出流stdout,一个是错误流stderr,而fflush的参数就是传流进出,这里是将数据输出,所以使用输出流

代码修改:

#include <stdio.h>
#include<unistd.h>
int main()
{printf("hello Makefile!");fflush(stdout);sleep(3);return 0;
}

在这里插入图片描述
大家看到达到我们想要的效果了吧。

1.3倒计时

结合上面讲的两个知识点,进行编写一个倒计时。

  1 #include"processBar.h"2 int main()3 4 {5     int cnt=9;6     while(cnt>=0)7     {8         printf("%d",cnt);9         fflush(stdout); //不加会显示不出来,最后会一起显示出来                                                                                                                                               10         sleep(1);11         cnt--;12     }13     return 0;14 }

不加:
在这里插入图片描述
加:
在这里插入图片描述

显然这两种都不是我们想要的倒计时,我们看看有一个特点,我们每输出一个时间光标就往后面跑一个字符,所以想要把之前的字符覆盖,就要是光标一直再开头的位置,所以我们再打印的时候加一个 \r

+\r
在这里插入图片描述
这才是我们想要的倒计时,但是这个程序还有一个小毛病,但从大于9开始倒计时就会出现问题,我们需要进行打印格式的调整

会出现下面的情况:

在这里插入图片描述
解决方法:(以%-2d的形式进行打印就可以了)
在这里插入图片描述

到这里我们的知识铺垫到此结束,接下来开始正式讲解进度条的实现

二、进度条

我们最终是要将我们的进度条模拟实现成多软件一起下载的场景,如下:
在这里插入图片描述

此次进度条的模拟实现,我打算使用多文件的方式,使用自动化构建来编写,我们开始做一些前期工作在这里插入图片描述
我们准备工作做好之后,我们开始来实现进度条代码吧

2.1基础进度条

设计思想: 在实现对多软件的模拟进度条下载,我们必须先弄清楚一个普通的进度条是怎么实现的吧。我们就需要使用到\r的特性,\r是回车的意思,将光标回到当前行开始的地方,我们采取的是先打印一个字符,然后再增加一个字符进行覆盖打印,如果是换行打印,就类似于一个直角三角形,我们来看代码实例:

  1. 错误示范
    在这里插入图片描述
    这个显然不是我们想要的效果,我们达到我们想要的推进式打印,但是想要打印在同一行,这时候就需要使用\r使光标变到第一行,然后一次一次的覆盖打印,但是要记得刷新。

  2. 正确操作
    在这里插入图片描述
    这个就符合我们想要的进度条了,但是这个进度条和我们一开始想要的还是有差别

  3. 将进度条放在一个框框里面,并且显示进度,这个需要了解C语言的打印格式,C语言默认是右对齐,我们想要每次打印从左往右,就需要采取左对齐,再框框里面预留100个位置,因为一次是增加一个字符,我们来看代码:
    在这里插入图片描述

  4. 等待旋转标志
    这个是告诉用户进度条再运行,给个提示,使用字符 **|/-\**循环打印来模拟实现再旋转的场景,看代码:
    在这里插入图片描述
    我们的第一代进度条就算是完成了,我们再来完善一下,使他变得可控一些
    在这里插入图片描述
    代码:

  1 #include"processbar.h"2 void processbar()3 {4     char bar[NUM]={0};5     int cnt=0;6     const char*label="|/-\\";7     int len=strlen(label);8     while(cnt<=100)9     {10         printf("[%-100s][%d%%][%c]\r",bar,cnt,label[cnt%len]);11         fflush(stdout);12         usleep(50000);//控制进度条的时间                                                                                                                               13         bar[cnt++]=STYLE;14     }15     printf("\n");16 }

2.2进阶进度条

我们要是想完成这个进阶进度条,就不能把循环放进一个函数里面,这样是不可控的,我们要专门写一个下载函数,来进行软件的下载,把下载的进度单独设置成一个函数,什么叫下载的进度,下面这就叫下载的进度

在这里插入图片描述
我们来修改代码:

 1 #include"processbar.h"2 3 //下载函数4 void download(int tatol,int internetspeep)//传软件总大小和下载速度5 {6     initbar();7     int cur=0;//从0MB开始下载8     while(cur<=tatol)9     {10         processbar(cur*100/tatol,tatol,internetspeep);//乘100是因为传进去里面有百分比,传当前进度,总大小和下载速度11         cur+=internetspeep;//internetspeepMB/s的速度下载12         usleep(1000000);13     }14     printf("\n");15 }16 //进度函数17 char bar[NUM]={0};//设置成全局的,因为再下载函数里面要频繁调用进度函数,而进度是一直推进的,放在进度函数里面会导致调用依次之后就会被销毁18 void initbar()//每次任务下载的之前都要初始化一下19 {20     memset(bar,'\0',sizeof(bar));21 }22 void processbar(int rate,int tatol,int internetspeep)//传当前进度进来,就是已经下载的大小占总大小的多少23 {24     const char*label="|/-\\";25     int len=strlen(label);                                                                                                                                             26     printf("[%-100s][%d%%][%c][%s%d%s]\r",bar,rate,label[rate%len],"已经下载了",tatol*rate/100,"MB");27     fflush(stdout);28     int count=internetspeep*100/tatol;29     while(count--)//每次进度条增加几条字符,按照下载速度占总大小的百分比老算30     {31        bar[rate++]=STYLE;32     }33 }

在这里插入图片描述
我们来看运行结果:
在这里插入图片描述


这样已经很符合我们平时下载的进度条了,但是我还想再优化一下时进度条好看一些---------->这样的形式
代码优化:在这里插入图片描述

在这里插入图片描述
颜色优化:(https://blog.csdn.net/wuquan_1230/article/details/106077560)参考这篇博客
代码:
在这里插入图片描述

在这里插入图片描述
这就实现了一个非常好看的进度条

三、总结

今天大家实现了Linux上的第一个小程序,进度条,希望大家下来可以自己去实现一下,还是比较好玩的,也可以修改成自己风格的进度条,我们今天的知识就讲解到这里了,下篇再见

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/7651.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

真赞!IDEA中可以这么玩MyBatis,让编码速度飞起!

本篇博客图解 MyBatis Generator 的使用过程&#xff0c;并结合实战说明逆向工程的使用方式。 搭建 MyBatis Generator 插件环境 a. 添加插件依赖 pom.xml <!--mybatis 逆向生成插件--> <plugin><groupId>org.mybatis.generator</groupId><artifac…

iPad平板用的触控笔什么牌子好?主动式电容笔推荐

现在&#xff0c;电容笔已经成为在线办公、在线教育等产业中的热门产品&#xff0c;那么&#xff0c;平替电容笔是否会代替苹果原有的电容笔呢&#xff1f;实际上&#xff0c;你根本不需要花那么多钱去买一个原装的苹果电容笔。一支普通的平替式电容笔只需要一两百元&#xff0…

微分方程应用——笔记整理

首先&#xff0c;根据正常思路走&#xff0c;化简得到式子&#xff1a; 不难发现&#xff0c;设 后面得出该方程的通解&#xff1a; 这里要注意什么等于这个通解 --- z 又因为该曲线过点 所以可以求出c为3 该题虽然简单&#xff0c;但是要注意几个问题&#xff0c;该定…

【封装丨工具类】

封装工具类 封装 Java 工具类1. 使用静态工厂方法或静态方法封装实例2.将工具类中的方法进行分组3. 常用方法定义为静态方法或枚举4. 工厂 | 抽象工厂模式5. 访问数据库5.1 JDBC API &#xff1a;5.2 第三方数据库 封装 Java 工具类 1. 使用静态工厂方法或静态方法封装实例 使…

netty学习(2):多个客户端与服务器通信

1. 基于前面一节netty学习&#xff08;1&#xff09;:1个客户端与服务器通信 只需要把服务器的handler改造一下即可&#xff0c;通过ChannelGroup 找到所有的客户端channel&#xff0c;发送消息即可。 package server;import io.netty.channel.*; import io.netty.channel.gr…

68、基于51单片机语音识别控制小车行走系统设计(程序+原理图+PCB源文件+参考论文+开题报告+任务书+元器件清单等)

摘 要 随着电子工业的发展&#xff0c;具有语音控制功能的小车越来越受到人们的青睐&#xff0c;在人们的日常消费生活中起着不可忽视的作用。目前&#xff0c;声控技术已在很多领域得到使用。 本文对语音控制功能的小车概况做了阐述。在硬件设计方面&#xff0c;本论文以凌阳…

LabVIEW评估儿童的运动认知技能

LabVIEW评估儿童的运动认知技能 以前测量认知运动功能的技术范围从基本和耗时的笔和纸技术&#xff0c;到使用准确但复杂和昂贵的实验室设备。Kinelab的主要要求是提供一个易于配置、坚固且便携的平台&#xff0c;以便在向4-12岁的儿童展示交互式视觉刺激期间快速收集运动学测…

blender 之点云渲染(论文渲图)

blender 之点云渲染&#xff08;论文渲图&#xff09; 一、导入点云1.新建2.导入点云3.位置移动&放大缩小 二、Geometry Nodes实体化点云1.新建节点2.实体化 三、给实体化点云添加材质四、设置渲染引擎更换为Cycles。 五、对准视角1.新建一个球2.创建相机视角跟踪3.将uv球挪…

LLM prompt提示构造案例

参考&#xff1a; https://github.com/PlexPt/awesome-chatgpt-prompts-zh 吴恩达 prompt工程应用&#xff1a; https://www.bilibili.com/video/BV1No4y1t7Zn prompt构造案例代码 prompt """文本分类任务&#xff1a;将一段用户给外卖服务的评论进行分类…

获取R、G、B通道的直方图

clc;%clc的作用就是清屏幕 clear;%clear是删除所有的变量 close all;%close all是将所有打开的图片关掉。imageimread(E:\我的桌面\MATLAB\练习\2.jpg);%绝对路径的 Rimage(:,:,1); Gimage(:,:,2); Bimage(:,:,3); hrimhist(R); hgimhist(G); hbimhist(B); x0:1:255; figure…

【探测器】opencv显示探测器的raw图像

【探测器】opencv显示探测器的raw图像 1、背景2、代码3、下载 1、背景 对于探测器&#xff08;相对于可见光成像的相机&#xff0c;这里的探测器指的是对X光成像的相机&#xff09;。 RAW文件几乎是未经过处理而直接从CCD或CMOS上得到的信息。 RAW格式是无损格式&#xff0c;相…

【什么是iMessage苹果推】怎样来获取设备令牌(Device Token)实现步骤

要获取设备令牌&#xff08;Device Token&#xff09;&#xff0c;您需要在应用程序中实现以下步骤&#xff1a; 在应用程序中请求用户授权&#xff1a;您需要请求用户授权允许应用程序发送远程通知。这可以通过使用 UNUserNotificationCenter&#xff08;User Notifications …