Linux 实现打印彩色进度条

news2024/11/19 7:35:26

文章目录

    • 预备知识
      • 一、理解回车换行
      • 二、认识行缓冲
      • 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数组,完成实现~~

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

在这里插入图片描述

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

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

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

相关文章

【数据结构和算法初阶(C语言)】双向循环带头链表的增删查改详解(天才设计的链表结构,应用简单逆天!!!!!)

目录 ​编辑​编辑 1.双向链表的定义&#xff1a;前赴后继 2.带头链表的定义-----哨兵位 3.增删查改 3.1创建新节点函数----方便后续增加节点调用 3.2创建哨兵位----创建头结点 3.3增加节点&#xff0c;尾部插入数据 3.4尾删除 3.5查找函数----遍历对比&#xff…

程序人生:当看到男友学测试拿高薪后,我突然悟了......

Hello&#xff0c;大家好&#xff0c;我是小雨 认识软件测试是因为我男朋友&#xff0c;他在华测教育培训软测后出去就业非常不错&#xff0c;所以我也萌生了转行的想法&#xff0c;当时我的想法是&#xff0c;他都能学会&#xff0c;那我肯定没问题&#xff0c;所以在他的介绍…

【编程系列----编译文件解析】Program size: Code, RO-data , RW-data, ZI-data

1.先给个 axf 文件 转编译bin文件的代码 2.解析下编译文件MAP 先给个编译提示 Code 是代码占用的空间 RO-data是 Read Only 只读常量的大小&#xff0c;如const型 RW-data是&#xff08;Read Write&#xff09; RW是可读可写变量&#xff0c;就是初始化时候就已经赋值了的&a…

图书管理系统的设计与实现

** &#x1f345;点赞收藏关注 → 私信领取本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345;** 一 、设计说明 1.1 课题…

鸿蒙Harmony应用开发—ArkTS声明式开发(通用属性:组件内容模糊)

为当前组件添加内容模糊效果。 说明&#xff1a; 从API Version 10开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 foregroundBlurStyle foregroundBlurStyle(value: BlurStyle, options?: ForegroundBlurStyleOptions) 为当前组件提供…

Linux 学习笔记(12)

十二、 系统服务 1 、系统服务分类&#xff0c;根据其使用的方法来分&#xff0c;可以被分为三类 a、由 init 控制的服务&#xff1a;基本都是系统级别的服务&#xff0c;运行级别这一章讲的就是这一类的服务 b、由 System V 启动脚本启动的服务&#xff1a;和我们打交道最多…

政务浏览器——打通信创闭环最后一公里

当前&#xff0c;信创建设工作主要集中在芯片、操作系统、数据库以及pc整机&#xff0c;这些领域基本可用&#xff0c;或者达到了市场主流水平。但是&#xff0c;政务办事场景下的信创落地仍然困难重重&#xff0c;很多地方不得不装双系统或买两台设备来来平衡日常业务和信创考…

关于企业数字化转型:再认识、再思考、再出发

近年来&#xff0c;随着国家数字化政策不断出台、新兴技术不断进步、企业内生需求持续释放&#xff0c;数字化转型逐步成为企业实现高质量发展的必由之路&#xff0c;成为企业实现可持续发展乃至弯道超车的重要途径。本文重点分析当下阻碍企业数字化转型的难点&#xff0c;提出…

[项目设计] 从零实现的高并发内存池(二)

&#x1f308; 博客个人主页&#xff1a;Chris在Coding &#x1f3a5; 本文所属专栏&#xff1a;[高并发内存池] ❤️ 前置学习专栏&#xff1a;[Linux学习] ⏰ 我们仍在旅途 ​ 目录 2.高并发内存池整体架构 3.ThreadCache实现 3.1 ThreadCache整体架构…

【JSON2WEB】08 Amis的事件和校验

CRUD操作中&#xff0c;新增、编辑、删除数据后要同步刷新列表&#xff0c;这个可以用Amis的事件来实现。 1 新增数据后刷新列表 Step 1 找到【新增数据】弹窗的【提交】按钮 Step 2 添加鼠标点击事件 这里的 组件ID&#xff1a;u:13d67a44214e 为表格2的组件ID&#xff0c; …

2024常用开源测试开发工具!

今天为大家奉献一篇测试开发工具集锦干货。在本篇文章中&#xff0c;将给大家推荐几款日常工作中经常用到的测试开发工具神器&#xff0c;涵盖了自动化测试、性能压测、流量复制、混沌测试、造数据等。 1、AutoMeter-API 自动化测试平台 AutoMeter 是一款针对分布式服务&…

MySQL 8.0.35 企业版安装和启用TDE插件keyring_encrypted_file

本文主要记录MySQL企业版TDE插件keyring_encrypted_file的安装和使用。 TDE说明 TDE( Transparent Data Encryption,透明数据加密) 指的是无需修改应用就可以实现数据的加解密&#xff0c;在数据写磁盘的时候加密&#xff0c;读的时候自动解密。加密后其他人即使能够访问数据库…

Vue-03

Vue指令 v-bind 作用&#xff1a;动态设置html的标签属性&#xff08;src url title…&#xff09; 语法&#xff1a;v-bind:属性名"表达式" 举例代码如下&#xff1a; 实现效果如下&#xff1a; 案例&#xff1a;图片切换 实现代码如下&#xff1a; 实现的效果…

#WEB前端(CCS常用属性,补充span、div)

1.实验&#xff1a; 复合元素、行内元素、块内元素、行内块元素 2.IDE&#xff1a;VSCODE 3.记录&#xff1a; span为行内元素&#xff1a;不可设置宽高&#xff0c;实际占用控件决定分布空间。 div为块内元素&#xff1a;占满整行&#xff0c;可以设置宽高 img为行内块元…

新手想玩硬件,买单片机还是树莓派好?

新手想玩硬件&#xff0c;买单片机还是树莓派好&#xff1f; 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「单片机的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#x…

单链表的排序-力扣算法题

文章目录 概要例题解题思路&#xff1a;1、递归分割2、递归排序实际的含义3、递归回溯与合并 case解析&#xff1a;1、初始链表&#xff1a;2、第一轮分割&#xff1a;3、继续分割&#xff1a;有序子链表合并&#xff1a;最终合并&#xff1a;结果&#xff1a; 代码实现总结&am…

JavaScript继承 寄生组合式继承 extends

JavaScript继承 1、JS 的继承到底有多少种实现方式呢? 2、ES6 的 extends 关键字是用哪种继承方式实现的呢? 继承种类 原型链继承 function Parent1() {this.name parentlthis.play [1, 2, 3] }function Child1() {this.type child2 }Child1.prototype new Parent1(…

(十)SpringCloud系列——openfeign的高级特性实战内容介绍

前言 本节内容主要介绍一下SpringCloud组件中微服务调用组件openfeign的一些高级特性的用法以及一些常用的开发配置&#xff0c;如openfeign的超时控制配置、openfeign的重试机制配置、openfeign集成高级的http客户端、openfeign的请求与响应压缩功能&#xff0c;以及如何开启…

bashplotlib,一个有趣的 Python 数据可视化图形库

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站AI学习网站。 目录 前言 什么是Bashplotlib库&#xff1f; 安装Bashplotlib库 使用Bashplotlib库 Bashplotlib库的功能特性 1. 绘…

Linux速览(1)——基础指令篇

在上一章对Linux有了一些基础了解之后&#xff0c;本章我们来学习一下Linux系统下一些基本操作的常用的基础指令。 目录 1. ls 指令 2. pwd&&whoami命令 3. cd 指令 4. touch指令 5.mkdir指令&#xff08;重要&#xff09;&#xff1a; 6.rmdir指令 && …