Linux 实现打印彩色进度条

文章目录

    • 预备知识
      • 一、理解回车换行
      • 二、认识行缓冲
      • 1、代码一、二(回车换行理解)
      • 2、代码三、四(sleep函数和ffush函数理解)
    • 三、简单倒计时
      • 1. 倒计时代码
      • 2、效果展示
    • 四、进度条
      • 1、效果展示
      • 2、进度条代码
        • makefile
        • ProcessBar.h
        • ProcessBar.c
        • main.c
      • 3、实现过程分析
        • 4.3.1 进度条实现样式
        • 4.3.2 进度条实现方法

预备知识

一、理解回车换行

  • 在我们熟悉的C语言中,换行就可以跳转的下一行开头 ,但其实这一操作有两个步骤,\r (回车)和 \n(换行)
  • 也就是先回到开头,再进行换行

\r 回车就是回到这一行开头
\n 换行就是另起一行

二、认识行缓冲

  • 在内存中预留了一块空间,用来缓冲输入或输出的数据,这个保留的空间被称为缓冲区。
  • 下面我们通过几个代码来理解一下:

1、代码一、二(回车换行理解)

代码一:

#include<stdio.h>

int main()
{
    printf("hello world\n");
    return 0;
}

在这里插入图片描述

代码二:

  • 那我将这个\n换成了\r,再次打印会出现什么情况?
#include<stdio.h>

int main()
{
    printf("hello world\r");
    return 0;
}

在这里插入图片描述

在这里插入图片描述

  • 发现 \n 可以打印出来,而 \r,不能打印出来,因为显示器模式是行刷新缓冲区是按行缓冲的,没有\n,就不能立即刷新。 \r 回到行首后,会进行覆盖写,shell 提示符会覆盖掉之前写的 “hello world”,如果我们在 “hello world” 不加 \r,则不会进行覆盖写,shell 提示符会顺着 “hello world” 往后写

如下:

在这里插入图片描述

2、代码三、四(sleep函数和ffush函数理解)

  • 行缓冲是缓冲区刷新策略的一种,在行缓冲模式下,当输入和输出中遇到 ‘\n’ 换行时,就会刷新缓冲区,下面我们认识头文件<unistd.h>的三个函数

sleep:Linux 下的休眠函数,单位是秒
usleep:和sleep 一样,单位ms(即10-6 m)
fflush :刷新缓冲区

代码 3:

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

int main()
{
    printf("hello world");
    sleep(3);
    return 0;
}

在这里插入图片描述

  • 我们写的这个C语言程序是从上到下依次执行的,而我们看到的是先休眠后打印
  • 这是因为数据保存在缓冲区中,没有主动刷新。当程序退出后,保存在缓冲区中的数据被自动刷新出来了,如果我们想提前刷新,便可以调用fflush函数来刷新缓冲区

代码四:

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

在这里插入图片描述

  • 这次 “hello world” 被直接打印出来,我们加 \n避免shell 提示符出现在 “hello world” 后面

三、简单倒计时

1. 倒计时代码

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

2、效果展示

在这里插入图片描述

具备了以上介绍的知识,接下来我们就实现进度条了

四、进度条

1、效果展示

在这里插入图片描述

2、进度条代码

makefile
processbar:ProcessBar.c main.c
        gcc -o $@ $^ 
.PHONY:clean
clean:  
        rm -rf processbar
ProcessBar.h
#pragma once
#include <string.h>
#include <unistd.h>
#include <stdio.h>

// 进度条箭头
#define TAIL '>'

// 进度条的数组大小
#define Length 102

// 进度条加载的进度条
#define Style '='

// 重定义函数指针
typedef void (*callback_t)(double, double);

// 进度条的实现
void ProcBar(double total, double current);
ProcessBar.c
#include "ProcessBar.h"

#define LIGHT_CYAN   "\033[1;36m" // 亮青色
#define NONE "\033[m" 	//截断

// 显示进度
const char* lable = "|/-\\";

void ProcBar(double total, double current)
{
    char bar[Length];
    // 初始化进度条
    memset(bar, '\0', sizeof(bar));
    int len = strlen(lable);

    int cnt = 0;
    double rate = (current * 100.0) / total;
    // 循环次数
    int loop_count = (int)rate;
    while (cnt < loop_count)
    {
        bar[cnt++] = Style;
        if (rate < 100)
            bar[loop_count] = TAIL;
    }
    // 打印显示
    printf(LIGHT_CYAN"[%-100s]"NONE"[%.2lf%%][%c]\r", bar, rate, lable[cnt % len]);
    // 刷新缓冲区
    fflush(stdout);
}

main.c
#include "ProcessBar.h"

// 网络带宽【1mb】
double bandwidth = 1024 * 1024 * 1.0;

void download(double filesize, callback_t cb)
{
    //  累计下载的数据量
    double current = 0.0;
    printf("download begin, current: %lf\n", current);
    while (current <= filesize)
    {
        // 使用函数指针更新界面
        cb(filesize, current);
        //从网络中获取数据
	//......
	
	// 睡眠
        usleep(100000);

        // 累计下载
        current += bandwidth;
    }
    printf("\ndownload done, filesize: %lf\n", filesize);
}

int main()
{
    // 测试调用
    //download(100 * 1024 * 1024, ProcBar);
    download(2 * 1024 * 1024, ProcBar);
    //download(200*1024*1024,ProcBar);
    //download(400*1024*1024,ProcBar);
    download(50*1024*1024,ProcBar);
    download(10*1024*1024,ProcBar);

    // 测试
    //ProcBar(100.0, 56.9);
    //ProcBar(100.0, 1.0);
    //ProcBar(100.0, 99.9);
    //ProcBar(100.0, 100);
    return 0;
}

3、实现过程分析

4.3.1 进度条实现样式

进度条样式 :

  • 进度条的主要内容是两个中括号包裹,中间进度显示以=>的方式进行推进呈现

进度条百分比:

  • 显示当前进度百分比,随着进度不断推进,百分比也在增加

进度条旋转字符:

  • 显示加载样式,可以利用一个旋转的字符,例如 [] 的样式,顺时针不断旋转,依次为 “| / - \”,注意 ** 也是转义字符,因此需要两个 *\ *

进度条颜色:

c语言颜色参考
我们可以根据自己的喜好给进度条上色,在此我们找到颜色参照表

4.3.2 进度条实现方法
  • 预留进度条大小为 100 个 = ,外加 1 个 > ,加上保存 \0 的位置,定义一个102个单位的长度的bar数组。

  • 如果将打印放在循环中的话,在打印的时候会变得卡卡的,我们可以将打印放到循环外面,等数组放上=>后,在一起打印,这样更好

  • 我们又实现了一个函数download(),把ProcBar(),作为参数传递给download(),用usleep函数模拟下载时间,然后循环起来回调processbar()函数,便实现了进度条

  • 最后考虑到第二次下载,bar数组满了,我们再每次调用download()函数时,清空bar数组,完成实现~~

  • 这就实现了我们最终的效果

在这里插入图片描述

最后本文就到这里结束了,感谢大家的收看,请多多指点~

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

从零开始搭建web组态

成果展示&#xff1a;by组态[web组态插件] 一、技术选择 目前只有两种选择&#xff0c;canvas和svg Canvas: 是一个基于像素的渲染引擎&#xff0c;使用JavaScript API在画布上绘制图像&#xff0c;它的优点包括&#xff1a; Canvas渲染速度快&#xff0c;适合处理大量图像和…

【STM32】STM32学习笔记-FLASH闪存(48)

00. 目录 文章目录 00. 目录01. FLASH简介02. 闪存模块组织03. FLASH基本结构04. FLASH解锁05. 使用指针访问存储器06. 程序存储器编程07. 选项字节08. 选项字节编程09. 选项字节擦除10. 器件电子签名11. 附录 01. FLASH简介 STM32F1系列的FLASH包含程序存储器、系统存储器和选…

【.NET Core】.NET中的流(Stream)

【.NET Core】.NET中的流&#xff08;Stream&#xff09; 文章目录 【.NET Core】.NET中的流&#xff08;Stream&#xff09;一、流&#xff08;Stream&#xff09;1.1 FileStream类1.2 IsolatedStorageFileStream类1.3 MemoryStream类1.4 BufferedStream类1.5 NetworkStream类…

STM32 (2)

1.stm32编程模型 将C语言程序烧录到芯片中会存储在单片机的flsah存储器中&#xff0c;给芯片上电后&#xff0c;Flash中的程序会逐条进入到CPU中去执行&#xff0c;进而CPU去控制各种模块&#xff08;即外设&#xff09;去实现各种功能。 2.寄存器和寄存器编程 CPU通过控制其…

公司电脑文件防泄密软件——| 中科数安

公司电脑文件防泄密软件是一种专门设计用于保护企业敏感信息和数据安全的软件。这些软件通过采用各种技术手段&#xff0c;如数据加密、访问控制、行为监控等&#xff0c;来防止公司的机密文件、客户资料、财务数据等被非法获取、复制或传播。 www.weaem.com 以下是公司电脑文件…

选项 打光 试题总结

试题1 被测物体100100mm&#xff0c;精度要求被测物体 &#xff0c;精度要求0.1mm&#xff0c;相机距被测物体在200&#xff5e;320mm之间&#xff0c;要求选择合适的相机和镜头&#xff1f; 分析如下&#xff1a; 通常我们用的相机靶面是4:3 的所以我们要用短边来计算视场&am…

Vue导出json数据到Excel表格

一、安装依赖 npm install file-saver --save npm install xlsx --save npm install script-loader --save-dev二、下载两个所需要的js文件Blob.js和 Export2Excel.js。 这里下载&#xff1a;下载地址 三、src目录下新建vendor文件夹&#xff0c;将Blob.js和 Export2Excel.j…

STM32学习和实践笔记(1): 装好了的keil μVision 5

2019年3月在淘宝上买了这块STM32的开发板&#xff0c;学了一段时间后就丢下了&#xff0c;今天重新捡起来&#xff0c;决定好好学习、天天向上。 对照教程&#xff0c;今天先把keil5装上了。 装的过程有以下几点值得记录下&#xff1a; 1&#xff09;用注册机时&#xff0c;…

x86中的TSS与任务切换

前言 今天在学习《深入理解Linux内核》的时候&#xff0c;发现出现了一个新的名词TSS&#xff08;Task-State Segment&#xff09;&#xff0c;这还是我第一次了解到原来x86提供了硬件级别的任务切换功能&#xff0c;之前以为任务切换都是操作系统实现的来着&#xff0c;这里也…

计算机电源的功率不足150W的几种主要原因?

180 至 250 伏 180-250伏 一般计算机电源的工作电压范围为 180 至 250 伏。 电脑电源是安装在电脑内部的电脑部件&#xff0c;负责将普通市电电源转换成电脑可以使用的电压。 电脑电源是一个开关电路&#xff0c;将普通交流电转换为直流电&#xff0c;然后通过斩波控制电压&a…

JavaScript 中的类型转换机制(详细讲解)

文章目录 一、概述二、显示转换Number()parseInt()String()Boolean() 三、隐式转换自动转换为布尔值自动转换成字符串自动转换成数值 一、概述 前面我们讲到&#xff0c;JS中有六种简单数据类型&#xff1a;undefined、null、boolean、string、number、symbol&#xff0c;以及…

你知道为什么输电线路除冰采用的是直流电而不是交流电呢?

2月22日以来&#xff0c;受新一轮寒潮影响&#xff0c;四川地区气温骤降&#xff0c;多地出现了零摄氏度以下的低温和冰冻天气&#xff0c;泥巴山、蓑衣岭等微气象区域20条500千伏线路出现不同程度覆冰&#xff0c;其中500千伏石雅四回线路覆冰最为严重&#xff0c;导线和铁塔上…

程序员在面试过程中需要重点关注的问题

在金三银四这个关键的求职季节&#xff0c;程序员面试的成功与否往往决定了他们能否获得心仪的工作机会。在这篇文章中&#xff0c;我将详细介绍程序员在面试过程中需要重点关注的问题&#xff0c;并提供一些实用的建议和技巧。 一、了解自己和职位要求 在面试之前&…

在线绘图利器:支持在线使用的电脑画图软件推荐!

计算机绘图软件是现代设计师和创作者必不可少的工具之一。伴随着技术的不断发展&#xff0c;越来越多的在线计算机绘图软件应运而生&#xff0c;为用户提供了更加便捷、高效的创作方法。对初学者而言&#xff0c;选择一款易于使用、功能强大的计算机绘图软件至关重要。本文将介…

39. 【Linux教程】修改文件所属关系

上一节介绍了如何修改文件的读、写、执行权限&#xff0c;包括属主用户权限、所属用户组权限、其他用户组用户权限&#xff0c;本小节介绍如何修改文件的所属关系&#xff0c;所属关系又包括文件的属主和所属组。 1.chown 命令 若想要修改文件的属主&#xff0c;可以使用 chow…

便携式启动电源的市场前景和商业机会

便携式启动电源是一种便携式电子设备&#xff0c;主要用于为飞机、火炮、汽车、船只等大型机械提供紧急启动电源。它通常由一个可充电的电池和一个充电器组成&#xff0c;可以方便地随身携带。 便携式启动电源的工作原理是通过将电池的电能转换为机械能&#xff0c;从而驱动汽…

Leetcoder Day38| 动态规划part05 背包问题

1049.最后一块石头的重量II 有一堆石头&#xff0c;每块石头的重量都是正整数。 每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c;且 x < y。那么粉碎的可能结果如下&#xff1a; 如果 x y&#xff0c;那…

云端技术驾驭DAY15——ClusterIP服务、Ingress服务、Dashboard插件、k8s角色的认证与授权

往期回顾&#xff1a; 云端技术驾驭DAY01——云计算底层技术奥秘、云服务器磁盘技术、虚拟化管理、公有云概述 云端技术驾驭DAY02——华为云管理、云主机管理、跳板机配置、制作私有镜像模板 云端技术驾驭DAY03——云主机网站部署、web集群部署、Elasticsearch安装 云端技术驾驭…

Java中继承的作用及解析

在 Java 中&#xff0c;继承是一种非常重要的面向对象编程特性。它的主要作用包括以下几个方面&#xff1a; 代码复用&#xff1a;通过继承&#xff0c;子类可以复用父类的代码&#xff0c;包括属性和方法。这样可以避免重复编写相同的代码&#xff0c;提高代码的复用性和可维护…

keycloak-鉴权springboot

一、环境描述 keycloak鉴权springboot的方式&#xff0c;此处简单介绍&#xff0c;springboot官方也提供了demo https://github.com/keycloak/keycloak-quickstarts/tree/latest/spring/rest-authz-resource-server 以及文档说明 Securing Applications and Services Guide…