C语言Linux进度条模拟

        在Linux字符界面中,使用yum、apt下载东西时会有一个图形化的进度条,可以告诉我们任务的执行进度。

        我们也可以通过C语言实现一个类似的进度条,并且可以做得更加美观。以后我们自己写的程序需要显示进度时就可以去调用我们自己实现的进度条。

进度条实现

        下面这个是apt的进度条,可以看到这个进度条是通过在 [ ] 中填充 '#' 来实现的进度递增,同时还会显示当前进度的百分比。

        实际上要实现这个进度条,并不复杂。我们可以创建一个数组,每次进度递增就往里面填充 '#'。

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

char bar[101] = ""; //100个#号,一个\0

int main()
{
    int rate = 0;   //速率
    while(rate <= 100)
    {
        usleep(50000)    //睡眠时间,不让进度条很快就执行完
        printf("[%s]\n", bar);
        bar[rate++] = '#';
    }

    return 0;
}

        这个程序的执行结果如下: 

        可以发现我们的进度条是打印出来了,但是还存在很多问题。首先这个进度条并不是在同一行打印出来的,并且 ']' 是紧跟最右边的 '#' 的。

        我们在打印进度条时,使用了 '\n' 换行,这是不正确的。我们应该使用 '\r' 回车。

'\n' 换行:使光标下移一格
'\r' 回车:使光标回到本行首位

        接下来,我们对代码进行改进。

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

char bar[101] = ""; //100个#号,一个\0

int main()
{
    int rate = 0;
    while(rate <= 100)
    {
        usleep(50000);
        printf("[%-100s]\r", bar);
        bar[rate++] = '#';
    }

    return 0;
}

        可以看到进度条确实是在同一行执行了,但是程序打印时并没有一个一个 '#' 的进行打印。而是一段一段的。 

        这是因为缓冲区没有立刻刷新,当时使用 '\n' 没有这个问题,是因为换行时就会刷新缓冲区。但是 '\r' 回车并不会刷新缓冲区,我们想实现立刻刷新缓冲区可以使用 fflush() 函数。

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

char bar[101] = ""; //100个#号,一个\0

int main()
{
    int rate = 0;
    while(rate <= 100)
    {
        usleep(50000);
        printf("[%-100s]\r", bar);
        fflush(stdout);    //stdout标准输出
        bar[rate++] = '#';
    }
    printf("\n");    //换行
    return 0;
}

         我们已经实现了一个正常的进度条了,现在可以对进度条进行美化加工,让它变得更加美观。

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

char bar[101] = ""; //100个#号,一个\0
char* table = "|/-\\";

int main()
{
    int rate = 0;
    while(rate <= 100)
    {
        usleep(50000);
        printf("[%-100s][%d%%][ %c ]\r", bar, rate, table[rate%4]);
        fflush(stdout);
        bar[rate++] = '#';
        if(rate < 100)
        bar[rate] = '>';
    }
    printf("\n");
    return 0;
}

        现在进度条实现了查看进度百分比和旋转光标,已经可以和 apt 的进度条媲美了。但是还不够,我们还可以给进度条加上颜色实现彩色的进度条。

C语言输出颜色-CSDN博客

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

#define NONE "\033[m"
#define LIGHT_GREEN "\033[1;32m"
#define LIGHT_CYAN "\033[1;36m"
#define LIGHT_PURPLE "\033[1;35m"

char bar[101] = ""; //100个#号,一个\0
char* table = "|/-\\";

int main()
{
    int rate = 0;
    while(rate <= 100)
    {
        usleep(50000);
        printf(LIGHT_GREEN"[%-100s]"NONE LIGHT_CYAN"[%d%%]"NONE LIGHT_PURPLE"[ %c ]"NONE"\r", bar, rate, table[rate % 4]);
        fflush(stdout);
        bar[rate++] = '#';
        if(rate < 100)
        bar[rate] = '>';
    }
    printf("\n");
    return 0;
}

         现在进度条已经写好了,现在我们要对它进行封装。把它的主体封装起来,方便我们后面去调用它。

        创建一个头文件和源文件。因为进度条本身是不知道一件事情的进度目前是多少,进度只有去调用进度条的人才知道,所以进度条的 rate 进度不能封装进去。

ssddffaa@Server-Ubuntu:~/mini-program/ProcessBar$ ls
main.c  Makefile  processbar.c  processbar.h  process-debug.out  process.out

 processbar.h

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

#define BAR 101
#define BODY '='
#define CUR '>'

#define NONE "\033[m"
#define LIGHT_GREEN "\033[1;32m"
#define LIGHT_CYAN "\033[1;36m"
#define LIGHT_PURPLE "\033[1;35m"

extern void processbar(int rate);

 processbar.c

#include "processbar.h"

char bar[BAR] = "";
const char* table = "|/-\\";

void processbar(int rate)
{
    printf(LIGHT_GREEN"[%-100s]"NONE LIGHT_CYAN"[%d%%]"NONE LIGHT_PURPLE"[ %c ]"NONE"\r", bar, rate, table[rate % 4]);
    fflush(stdout);
    bar[rate++] = BODY;
    if (rate < 100)
        bar[rate] = CUR;
    if (rate == 101)
    memset(bar, '\0', sizeof(bar));
}

main.c

#include "processbar.h"
typedef void (*callbar)(int);

void Download(callbar cb)
{
    int total = 1100;
    int cnt = 0;
    while (cnt <= total)
    {
        usleep(50000);
        int rate = cnt*100 / total;
        cb(rate);
        cnt += 10;
    }
    printf("\n");
}

int main()
{
    Download(processbar);
    return 0;
}

         至此,进度条就写完啦。我们后面想在自己的项目中去使用时就可以通过包含头文件的方式去调用进度条函数。

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

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

相关文章

【算法】贪心算法——柠檬水找零

题解&#xff1a;柠檬水找零(贪心算法) 目录 1.题目2.题解3.参考代码4.证明5.总结 1.题目 题目链接&#xff1a;LINK 2.题解 分情况讨论 贪心算法 当顾客为5元时&#xff0c;收下当顾客为10元时&#xff0c;收下10元并找回5元当顾客为20元时&#xff0c;收下20元并找回10…

图像交换部分区域或帧

生成一个boundingbox&#xff0c;或区间 给定矩形框占图像的面积比例&#xff0c;和图像的宽W高H&#xff0c;生成矩形框。根据给定的矩形框&#xff0c;交换两张图像的部分区域。 这里为了方便展示&#xff0c;简化问题&#xff0c;给定一个图像数组mels&#xff0c;对第 i …

基于SSM框架的垃圾分类系统的设计与实现(含源码+sql+开题报告+论文+论文答辩模板)

图1 前台首页截图 首页展示&#xff1a;首页展示法律法规、公示公告、用户交流论坛、分类指南、垃圾站点、以及个人中心&#xff1b; 法律法规&#xff1a;展示我国《城市生活垃圾分类及其评价标准》以及《生活垃圾分类标志》等最新法律法规&#xff1b; 公示公告&#xff1…

【第1章】SpringBoot实战篇之注册接口

文章目录 前言一、代码部分1. User2.UserMapper13. UserSerivce4. UserController15. Result 二、测试1.注册2.再次注册 总结 前言 下面介绍用户注册接口。 一、代码部分 1. User package org.example.springboot3.bigevent.entity;import com.baomidou.mybatisplus.annotat…

【Vulhub】Fastjson 1.2.24_rce复现

文章目录 一&#xff0c;Fastjson是什么&#xff1f;二&#xff0c;fastjson漏洞原理三&#xff0c;判断是否有fastjson反序列化四&#xff0c;复现Fastjson 1.2.24_rce(vulhub)环境配置1.判断是否存在Fastjson反序列化2.反弹shell3.启动RMI服务器4.构造恶意POST请求 一&#x…

FineBi导出Excel后台版实现

就是不通过浏览器,在后台运行的导出 参考文档在:仪表板查看接口- FineBI帮助文档 FineBI帮助文档 我这里是将这个帮助文档中导出的excel文件写到服务器某个地方后,对excel进行其他操作后再下载。由于原有接口耦合了HttpServletRequest req, HttpServletResponse res对象,…

【代码随想录】【算法训练营】【第24天】 [77]组合

前言 思路及算法思维&#xff0c;指路 代码随想录。 题目来自 LeetCode。 day 23&#xff0c;愉快的周五~ 题目详情 [77] 组合 题目描述 77 组合 解题思路 前提&#xff1a;组合求子集问题 思路&#xff1a;回溯算法三部曲&#xff1a;递归函数的返回值以及参数、回溯…

MySQL 自定义函数(实验报告)

一、实验名称&#xff1a; 自定义函数 二、实验日期&#xff1a; 2024年 6 月 1 日 三、实验目的&#xff1a; 掌握MySQL自定义函数的创建及调用&#xff1b; 四、实验用的仪器和材料&#xff1a; 硬件&#xff1a;PC电脑一台&#xff1b; 配置&#xff1a;内存&#…

数据结构——图论详细笔记

一 图论基本概念 Directed Acyclic Graph &#xff08;DAG&#xff09; 二 图的存储 ①邻接矩阵(适用于稠密图) ②邻接表(适用于稀疏图) 三、图的遍历 ①深度优先搜索 //(基于邻接表实现&#xff0c;以有向图为例) //DFS:Depth First Search 深度优先搜索 //1、访问起始顶点 …

STM32学习和实践笔记(33):待机唤醒实验

1.STM32待机模式介绍 很多单片机具有低功耗模式&#xff0c;比如MSP430、STM8L等&#xff0c;我们的STM32也不例外。默认情况下&#xff0c;系统复位或上电复位后&#xff0c;微控制器进入运行模式。在运行模式下&#xff0c;HCLK 为CPU提供时钟&#xff0c;并执行程序代码。这…

【GPU原理】1.线程和缓存的关系

一、GPU如何做并行计算 1.简单的串行计算 对于如上的运算AXY&#xff0c;每次运算我们需要从内存读取两个数据&#xff0c;一个是x[i]&#xff0c;一个是y[i]&#xff0c;最后存回y[i]。这里面有一个FMA的操作&#xff08;融合乘加&#xff08;FMA&#xff09;指令是RISC处理器…

基于Qt GraphicView 解析 CIM/G 电力接线图文件

本文讲述了如何使用Qt的框架来渲染展示标准的CIM/G格式的图形文件&#xff0c;也就是公用信息模型&#xff08;common information model&#xff0c;CIM&#xff09;中的G文件部分的内容。这是一种电力系统图形的交换规则&#xff0c;用于电网图形交换。 [by amjieker] CIM/G …

Ai晚班车531

1.中央网信办等三部门&#xff1a;加快推进大模型、生成式人工智能标准研制。 2.中国石油与中国移动、华为、科大讯飞签署合作协议。 3.Opera浏览器与谷歌云合作&#xff0c;接入 Gemini 大模型。 4.谷歌 Gemini 加持Chromebook Plus。 5.英飞凌&#xff1a;开发 8kW和12kW…

《技术人求职之道》:从入职到离职,全方位解析求职艺术

一、引言二、内容&#xff1a;该求职专栏包含什么三、结果&#xff1a;通过该专栏你将收获什么四、说明&#xff1a;关于该专栏的一些问题解答五、后记 一、引言 求职&#xff0c;这是每个人职业生涯中必经的阶段&#xff0c;技术人亦不例外。上一个冬天的寒风已过&#xff0c…

获取 Bean 对象更加简单的方式

获取 bean 对象也叫做对象装配&#xff0c;是把对象取出来放到某个类中&#xff0c;有时候也叫对象注⼊。 对象装配&#xff08;对象注⼊&#xff09;即DI 实现依赖注入的方式有 3 种&#xff1a; 1. 属性注⼊ 2. 构造⽅法注⼊ 3. Setter 注⼊ 属性注入 属性注⼊是使⽤ Auto…

MySQL性能分析工具——EXPLAIN

性能分析工具——EXPLAIN 1、概述 定位了查询慢的SQL之后&#xff0c;我们就可以使用EXPLAIN或DESCRIBE工具做针对性的分析查询语句 。 DESCRIBE语句的使用方法与EXPLAIN语句是一样的&#xff0c;并且分析结果也是一样的。 MySQL中有专门负责优化SELECT语句的优化器模块&…

报表工具DataEase技术方案(二)

一、DataEase报表功能开发流程 1. 创建数据源 2. 创建数据集 可以创建多种来源的数据集&#xff0c;这里以SQL数据集为例。 数据集SQL中可以添加参数&#xff0c;仪表板展示数据时可以根据参数来筛选数据。 数据集添加计算字段 3. 创建仪表板 &#xff08;1&#xff09;组合…

关于Posix标准接口和Nuttx操作系统

基本介绍 主要参考&#xff1a; Linux 系统中的 POSIX 接口详细介绍_linux posix-CSDN博客 POSIX&#xff08;Portable Operating System Interface&#xff0c;可移植操作系统接口&#xff09;是由 IEEE&#xff08;Institute of Electrical and Electronics Engineers&#x…

LLVM入门教学——SanitizerCoverage插桩(Linux)

1、介绍 LLVM 的 SanitizerCoverage 是一种代码覆盖工具&#xff0c;设计用于支持基于 fuzzing 的测试和其他安全相关工具。SanitizerCoverage 在编译时插桩代码&#xff0c;以在运行时收集覆盖信息&#xff0c;从而帮助识别未覆盖的代码路径&#xff0c;提高测试的有效性和全…

详细介绍运算符重载函数,清晰明了

祝各位六一快乐~ 前言 1.为什么要进行运算符重载&#xff1f; C中预定义的运算符的操作对象只能是基本数据类型。但实际上&#xff0c;对于许多用户自定义类型&#xff08;例如类&#xff09;&#xff0c;也需要类似的运算操作。这时就必须在C中重新定义这些运算符&#xff…