【Linux】进度条小程序

news2024/10/7 20:36:13

目录

  • 一.\r && \n
  • 二.行缓存区概念
    • 问题:
    • 解答:
    • 检测:
  • 三.进度条
    • 1.进度动态条
    • 2.进度百分比
    • 3.小装饰
    • 4.颜色

该篇博客会主要按步骤推导出一个在Linux上运行的进度条小程序,会用到vim编辑器和gcc编译器,如果对这两个软件不熟悉,可以点击链接,结合该篇博客学习,进度条小程序展示如下:
在这里插入图片描述

一.\r && \n

c语言有很多的字符,但宏观上可以分为两种:可显字符控制字符

可显字符:A、a、B、c…等字符

控制字符:\n(回车)、\t(水平制表)、\r(换行)等

这里我们需要在Linux系统下使用\r\n两字符

一般,我们在C语言中使用\n进行换行,或在使用电脑的Enter键进行换行,是直接将其换到下一行的最左侧处

int main()
{
	printf("Hello\nWorld!");

	return 0;
}

在这里插入图片描述

但事实上,这是两个动作,只是在语言的范畴,C语言使用\n完成了换到下一行回到当前最左侧这两个动作。

像我们之前的老式键盘,回车键与现在的回车键不同,表示该键位是两个动作的和。

在这里插入图片描述
所以我们平时所指的换行都是由这两个动作组成的。

了解了上面的知识,我们在来看一下\r\n的意义

\r:回车(回到当前行最左侧)

\n:换行(换到下一行)

在这里插入图片描述
在我们使用C语言进行\n换行,在语言层面,默认进行了换行+回车两个动作

二.行缓存区概念

问题:

我们首先观察下面两个段代码的在Linux下运行后的区别

  • 会将两段代码的可执行文件都命名位MyTest,并运行展示

  • 代码中会用到sleep函数,可以使用man指令,在3号手册中查找(Linux常见指令)

    man 3 sleep
    

    在这里插入图片描述

    • 作用:在当前代码处暂停,单位秒。

代码1

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

int main()
{
   printf("hello world\n");//使用换行符'\n'
   sleep(3);//暂停3秒后继续运行
   return 0;
}

在这里插入图片描述
代码2

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

int main()
{
   printf("hello world\r");//使用回车符'\r'
   sleep(3);//暂停3秒后继续运行
   return 0;
}

在这里插入图片描述

按照我们正常的逻辑,两段代码都应该打印出东西,但是代码2只执行了sleep,什么都没有打印出来,这是为什么?是不是和\r\n有关系呢?

这个问题就涉及到了缓存区的概念(我们这里简单的了解一下,缓冲区剩余的内容会在之后的博客中)

解答:

我们在来看一下,下面这段代码及其运行结果:

代码3

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

int main()
{
   printf("hello world");
   sleep(3);//暂停3秒后继续运行
   return 0;
}

在这里插入图片描述

我们可以看到上面的结果,好像这次是先执行了sleep函数,在执行了printf,又在输出的字符串后,输出了命令行。

  • C语言的代码执行的是顺序结构,必须按顺序和代码逻辑依次执行,所以一定是printf先执行,然后是sleep。

  • printf即被执行,需要有一个地方临时存放字符串,这个地方就是缓存区

  • 当代码被执行完,缓存区被刷新,字符串被打印到屏幕上,此时光标(绿色光标)的位置在字符串的后面。

  • 在Linux中,每次像显示器打印数据都是从光标的位置开始,即:光标和显示器匹配,光标在哪里,就在哪里开始打印。

  • 所以命令行会直接打印在字符串后面。(代码1进行了换行,光标在新的一行)

  • 不同的平台缓冲区的表现形式不同,在Linux中,缓存区有自己的刷新策略(很多)

    我们现在看的是行缓存,它会在六种情况下刷新缓存区(只介绍三条,其余内容与该文无关)

    1. 遇到换行符,如:\n。(代码1先看到字符串后sleep的原因)
    2. 程序结束的时候。(代码三的情况)
    3. 主动刷新

从上面的内容,我们就能分析除代码2执行不成功的原因:

printf函数执行后,并没有使缓冲区刷新,数据保存在缓冲区内,执行sleep后,字符串在显示器上打印,但在之前的内容中我们指定\r为回车,将光标返回到这一行的最左边,然后命令行在光标开始处打印,将字符串内容覆盖。我们什么都看不到了。

那有办法解决这个问题吗?答:我想不出来,只要我们还将\r放在字符串最后面,字符串终会被命令行覆盖,即使我们使用其他控制字符,显示出结果,但结果终究和我们想要的不同。

这里我们倒是可以利用上面介绍的刷新缓存的第三种方法,来检测我们的解答是否正确,看到字符串在屏幕上出现并消失。

检测:

我们要主动刷新缓冲区,需要使用fflush函数,我们同样可以用man指令在3号手册中查找。Linux常见指令

man 3 fflush

在这里插入图片描述

测试代码如下:

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

int main()
{
   printf("hello world\r");//使用回车符'\r'
   fflush(stdout);//自动刷新缓存区
   sleep(3);//暂停3秒后继续运行
   return 0;
}

在这里插入图片描述

我们从结果看出,事实就是如此,它的光标移到了最左边,命令行打印时将其覆盖,我们在代码3中看不到结果。

拓展

凡是向显示器打印的所有的内容,都是字符

printf("%d",123);
//打印的123,分别为'1'、'2'、'3'

三.进度条

展示效果:

在这里插入图片描述
我们可以利用上面缓存区的知识,使用C语言在Linux上实现这样的一个小程序

一个这样的小程序我们可以简单将其分为如下图的四个部分:

在这里插入图片描述

1.进度动态条

进度条的增长的图形我设置为 = ,并以 > 符号开头

进度条的设置是从0%到100%(0%无进度),我们需要大小100个=,还需要1个 > ,在最后加一个终止符\0,共102个字节存储,也就是存储进度条的char类型的数组大小为102。

注意:创建了数组后,需要对其继续初始化,使其102个字节都为\0,方便每次到达更新的位置后准确停下。

我们要它每加载百分之一就刷新一次,我们需要将要打印的数组放在循环内,将\r放在要打印的字符串后面,在使用fflush(stdout)来自动刷新缓存区,在使用usleep(sleep单位秒,usleep单位微妙,可以自己尝试一下看看用那个更合适)将每次循环暂停一下在继续,这样就能展示出进度条上涨的形状。

在这里插入图片描述
在这里插入图片描述

2.进度百分比

我们在循环被打印进度条,只要打印时在将循环的次数打印即可,注意:百分号表示为%%,不能使用\%,会报警,有先平台上编译会显示失败。

修改上述代码如下

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

3.小装饰

在进度条的最后,我们增加了一个旋转的光标,使其看着更加生动,

这里使用| / - \四个符号来表示光标,将其存入数组,注意:\表示转移字符,要使用两个\来表示一个

顺时针旋转:“|/-\”

逆时针旋转:“|\-/”

这里使用顺时针,完整的修改代码如下:

  #include<stdio.h>    
  #include<unistd.h>    
  #include<string.h>    
      
  #define N 101    
  #define STYLE '='    
      
  int main()    
  {    
    char bar[N];    
    memset(bar,'\0',sizeof(bar));    
    char lable[4] = "|/-\\";    
    int i=0;    
    while(i<=100)    
    {    
      printf("[%-100s][%d%%][%c]\r",bar,i,lable[i%4]);                                                                                      
      fflush(stdout);    
      usleep(100000);    
      bar[i++] = STYLE;    
      if(i!=100) bar[i] = '>';    
    }    
    printf("\n");    
    return 0;    
  }   

在这里插入图片描述

4.颜色

想要使我们输出的进度条改变颜色有很多种方法,这里我只展示一种,有兴趣的可以自己去搜索

//格式
printf("\e[31;42m字符串\e[0m");

//31:前景色
//42:后景色
//\e[31 :开头
//\e[0m :终止,使改变的颜色只在字符串内

前景色(字体颜色)

字符颜色
30黑色
31红色
32绿色
33黄色
34蓝色
35紫色
36深绿
37白色

背景色

字符颜色
40黑色
41红色
42绿色
43黄色
44蓝色
45紫色
46深绿
47白色

有了这些知识,我们就能改变进度条的颜色,将其变为红色,代码如下:

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

#define N 101
#define STYLE '='

int main()
{
  char bar[N];
  memset(bar,'\0',sizeof(bar));
  const char* lable = "|/-\\";
  int i=0;
  while(i<=100)
  {
    printf("[\033[31m%-100s\033[0m][%d%%][%c]\r",bar,i,lable[i%4]);                                                               
    fflush(stdout);                                                   
    usleep(100000);                                                   
    bar[i++] = STYLE;
    if(i!=100) bar[i] = '>';
  }                         
  printf("\n");             
  return 0;    
}  

在这里插入图片描述
关于进度条颜色和形状不仅仅只有这些,大家感兴趣可以去搜索更多的内容,自己创建一个特别的进度条。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Centos7安装、卸载nginx及配置,配置成系统服务(一步到位)

目录 前言 一、下载安装解压 1.进入临时文件夹里&#xff08;随便一个都行&#xff09; 2.下载并安装nginx压缩包 3.解压该压缩包 4.创建目标文件夹 5.&#xff08;默认会安装在/usr/local/nginx&#xff09;这里通过configure命令指定安装目录 6.编译安装 7.最后生成的…

一、初始Numpy

1、numpy简介 简介 Numpy&#xff08;Numerical Python&#xff09;是Python语言的一个扩展程序库&#xff0c;支持大量的维度数组与矩阵运算&#xff0c;此外也针对数组运算提供大量的数学函数库 Numpy的前身Numeric最早是有Jim Hugunin与其他协作者共同开发&#xff0c;20…

十五天学会Autodesk Inventor,看完这一系列就够了(九),主题/色彩/单位设置

众所周知&#xff0c;Autocad是一款用于二维绘图、详细绘制、设计文档和基本三维设计&#xff0c;现已经成为国际上广为流行的绘图工具。Autodesk Inventor软件也是美国AutoDesk公司推出的三维可视化实体模拟软件。因为很多人都熟悉Autocad&#xff0c;所以再学习Inventor&…

使用SpringBoot创建web项目,并使用外部Tomcat

使用SpringBoot创建web项目&#xff0c;并使用外部Tomcat 目录使用SpringBoot创建web项目&#xff0c;并使用外部Tomcat简单介绍&#xff1a;特点&#xff1a;步骤简介下面就使用SpringBoot创建一个web工程&#xff0c;并且使用外部的Tomcat和实现对jsp的支持&#xff1a;一、创…

AIDL 应用间简单通信demo及基本问题

AIDL:Android Interface Definition Language,即Android接口定义语言。 他的作用大家已经知道了&#xff0c;有些童鞋对于其中的使用细节可能会有一些理解误差&#xff0c;并且会造成一写异常或者通讯失败。 我们先看几个关键点再看代码&#xff0c;如果项目不符合这几点&…

ffmpeg编译android平台-(ubuntu+ndkr16b+ffmpeg3.4.12)

一、环境配置 1、下载NDK,NDK老版本 1.1、 ubuntu下载 wget https://dl.google.com/android/repository/android-ndk-r16b-linux-x86_64.zip1.2、解压NDK unzip android-ndk-r16b-linux-x86_64.zip1.3、配置NDK环境变量 vim /etc/profile1.4、 在profile文件中添加如下内容…

String.prototype.matchAll called with a non-global RegExp argument

如上 matchAll这个API 与 正则的全局匹配是不一样的。他会将匹配到的所有字符串以迭代器的形式返回出来。 我们可以使用Array.from或者数据解构来获得匹配到的数组。 他与正则全局匹配的区别是当正则表达式包含()捕获组的时候&#xff0c;全局匹配无法获得子匹配组的数据。 …

【Datewhale一起吃瓜 Task1】周志华西瓜书第一章+第二章

这里写目录标题机器学习是干什么的机器学习的理论基础: PAC模型基本术语关于数据关于假设关于模型训练机器学习任务分类归纳偏好模型的评估和选择训练流程划分数据集的方法留出法交叉验证自助法性能度量机器学习是干什么的 我们目前处于大数据时代&#xff0c;每天会产生数以亿…

一个监控系统的典型架构是什么样的

典型架构 采集器是负责采集监控数据的,采集到数据之后传输给服务端,通常是直接写入时序库。然后就是对时序库的数据进行分析和可视化,分析部分最典型的就是告警规则判断(复杂一些的会引入统计算法和机器学习的能力做预判),即图上的告警引擎,告警引擎产生告警事件之后交给…

华为MPLS跨域带RR实验配置

目录 Option B方案实验配置 配置建立Vpnv4邻居 配置反射器 配置RR和ASBR取消RT值检测 配置ASBR相连接口开启MPLS 配置ASBR向RR发送路由时更改下一跳 Option C1方案实验配置 Option C2方案实验配置 接口IP地址、底层IGP路由协议&#xff08;ISIS&#xff09;、MPLS LDP协…

一种环状二肽3705-26-8,cyclo(Pro-Phe),环(PHE-PRO)环状二肽

基础产品数据&#xff08;Basic Product Data&#xff09;&#xff1a;CAS号&#xff1a;3705-26-8中文名&#xff1a;环(PHE-PRO)英文名&#xff1a;cyclo(Pro-Phe)&#xff0c;CYCLO(-PHE-PRO)结构式&#xff08;Structural&#xff09;&#xff1a;详细产品数据&#xff08;…

qq消息撤回

开发工具 工具名称工具类型说明AndroidStuduo编辑工具开发工具jadxjava工具将apk解成java项目xposed插件工具插件qq版本8.8.80 开始 先通过jadx把apk反编译出来源码&#xff0c;通过build出来&#xff0c;在android studio打开&#xff0c;方便分析。 要撤回自己的消息&…

TMC步进电机驱动stealthChop

一直觉得tmc系列的芯片功能很强大&#xff0c;但是我自己读寄存器手册的感觉就是每个字我都认识&#xff0c;怎么就这么难懂。。。。 stealthChop 是一种电压控制技术&#xff0c;基于电压斩波器的工作远离&#xff0c;可在低速中速范围内以最大扭矩实现绝对静音的步进电机控制…

【推荐】自用软件工具推荐 WIN

一、图片查看器 Honeyview 蜂蜜浏览器 免费的图像查看器 下载和功能说明 (bandisoft.com) 轻量而快速可以显示包括 GPS 信息在内的 JPEG 格式的 EXIF 信息对图像格式进行批量转换和调整大小支持显示 GIF 和 WebP 动图无需解压即可直接查看压缩包中的图像支持的格式 图像格式…

大厂整个项目的开发规范流程

第1节、大厂码农开发基础 内容 本章节给大家介绍在互联网做开发&#xff0c;基础环境、开发技术以及上线和监控都会用到哪些东西。一般互联网大厂像阿里、京东、腾讯等都会有公司自研的一些技术组件&#xff0c;比如&#xff1a;RPC、MQ、数据库路由等&#xff0c;但所有的这些…

API 网关的功能用途及实现方式

1. API 网关诞生背景 前言 API 经济生态链已经在全球范围覆盖&#xff0c; 绝大多数企业都已经走在数字化转型的道路上&#xff0c;API 成为企业连接业务的核心载体&#xff0c; 并产生巨大的盈利空间。快速增长的 API 规模以及调用量&#xff0c;使得企业 IT 在架构上、模式…

flume整合数据到kafka,sparkStreaming消费数据,并存储到hbase和redis中

目录 1、模拟数据生成 2、flume采集数据 1、node01配置flume的conf文件 2、node02开发flume的配置文件 3、node03开发flume的配置文件 4、开发flume启动停止脚本 5、node01执行以下命令创建kafka的topic 6、启动并查看kafka的数据 3、SparkStreaming消费kafka中的数…

第二章.线性回归以及非线性回归—LASSO算法

第二章.线性回归以及非线性回归 2.13 LASSO算法 1.前期导入&#xff1a; 通过构造一个一阶惩罚函数获得一个精炼的模型&#xff1b;通过最终确定一些指标(变量)的系数为零&#xff0c;解释力很强 岭回归估计系数等于0的机会微乎其微&#xff0c;造成筛选变量困难 擅长处理具有…

如何实现根据环境切换不同配置?

在企业开发中&#xff0c;系统的配置信息往往会分不同的环境&#xff0c;如开发环境、测试环境、生产环境。当我们使用nacos做为配置中心时&#xff0c;一定会遇到的问题就是在应用中配置nacos的server-addr时测试环境的nacos地址和线上nacos地址如何区分的问题 拿开发环境和正…

4.4 可迭代对象(Iterable)与迭代器(Iterator)

4.4 可迭代对象(Iterable)与迭代器&#xff08;Iterator&#xff09; 4.4.1 可迭代&#xff08;Iterable&#xff09;对象 如果一个对象实现了__iter__方法&#xff0c;那么这个对象就是可迭代&#xff08;Iterable&#xff09;对象>>> #如何知道一个对象实现了那些…