【Linux】简易进度条的实现

小伙伴们大家好,本片文章将会讲解
Linux中进度条的实现的相关内容。
如果看到最后您觉得这篇文章写得不错,有所收获,麻烦点赞👍、收藏🌟、留下评论📝。您的支持是我最大的动力,让我们一起努力,共同成长!
文章目录
- `1. 关于回车 & 换行`
- `2. 简述缓冲区`
- `3. 倒计时程序的编写`
- `4. 简易进度条的实现`
1. 关于回车 & 换行
回车和换行是文本显示和处理的相关术语,我们常常认为这两个是同一概念,实则不然。
👨💻回车换行的概念
回车(Carriage Return):在打字机时代,回车指的是将打字机的打印头(称为"carrier")移回到行首的操作。在计算机时代,回车通常表示将光标移动到当前行的开头,而不会换到下一行。在
ASCII字符集中,回车通常用"\r"表示。换行(Line Feed)::换行是指将光标移动到下一行的操作,使得文本在纵向上向下移动一个行高。在
ASCII字符集中,换行通常用"\n"表示。
在Unix和类Unix系统(如
Linux和macOS)中:通常使用换行字符(“\n”)来表示换行。
在Windows系统中:,通常使用回车和换行的组合来表示换行,即"
\r\n"。
2. 简述缓冲区
缓冲区(
Buffer)是计算机内存中的一块特定区域,用于临时存储数据。它在许多计算机系统和应用程序中发挥着重要作用,通常用于临时存储输入数据、输出数据或在内存和其他设备之间进行数据传输。
输入缓冲区:用于暂时存储从输入设备(如键盘、鼠标、网络接口等)接收到的数据,直到程序能够处理它们。输入缓冲区使得程序可以按需处理输入,而不必担心输入数据的速度与程序处理速度不匹配的问题。
输出缓冲区:用于暂时存储将要发送到输出设备(如显示器、打印机、网络接口等)的数据,直到设备准备好接收它们。输出缓冲区可以提高数据传输的效率,因为程序不必等待设备就绪就可以继续执行。
👨💻缓冲区何时被清理
拿C语言举个例子:
在C语言中,标准库函数printf()用于将格式化的数据打印到标准输出流(通常是终端)。但是,printf()函数并不会立即将数据显示到终端上。相反,它会将数据写入到输出缓冲区中。输出缓冲区是一个临时存储区域,用于存放printf()函数打印的数据,直到满足一定条件时才将其刷新(即将数据发送到终端并显示出来)。
这些条件包括:
1. 遇到换行符
\n:当printf()函数遇到换行符时,输出缓冲区会被自动刷新,将缓冲区中的数据输出到终端并显示出来。
2. 缓冲区满:当输出缓冲区满了,它也会被自动刷新。
3.调用fflush()函数:显式调用
fflush(stdout)函数可以强制刷新输出缓冲区,将其中的数据输出到终端。
4. 程序结束:当程序正常终止时,所有的缓冲区都会被刷新。
3. 倒计时程序的编写
有了以上的知识储备,咱们就可以尝试编写一下简单的倒计时程序了,思路如下:
- 首先新建一个
time.c文件,然后再用我们之前讲的makefile工具来实现time.c文件的自动构建:

- 编写
time.c这个文件,实现思路:
- 假设我们倒数
10s,到0s时结束,因此需要一个循环;- 循环中,我们要实现每次出来一个数,都要对之前的数进行覆盖,所以要用到回车"
\r";- 由于
printf()函数会会将输出的结果先输出到缓冲区,回车不会冲刷缓冲区,因此每次要用fflush(stdout)强制冲刷缓冲区;- 每次循环
秒数减1,并让程序休眠1s。
🌝详细代码如下:
#include <stdio.h>
#include <unistd.h>
int main()
{int cnt = 10;while(cnt >= 0){// 打印的时候每次覆盖上一次出现的数字printf("倒计时:%2d\r",cnt);// 强制冲刷缓冲区fflush(stdout);--cnt;sleep(1);}printf("\n");return 0;
}
- 用
make命令进行编译:(⏳这边就可以动态运行了哈,感兴趣的可以自己试一下⌛)

- 这里有个小拓展,如果我们要覆盖上次的数字是4位,这次是三次(比如1000到999),可以用
%4d这个输出形式来解决,也可以用下面这种方法:
#include <stdio.h>
#include <unistd.h>
int main()
{int cnt = 1000;int tmp = cnt;int num = 0;while (tmp){++num;tmp /= 10;}while(cnt >= 0){// 主要就是这里的变化,用最大数字的位数来做占位符printf("倒计时:%*d\r",num, cnt);fflush(stdout);--cnt;sleep(1);}printf("\n");return 0;
}
4. 简易进度条的实现
好啦,有了以上的知识作为基础,咱们就可以进入正题啦!😎编写简易的进度条。😎
👨💻效果图展示
总共有三个部分:
1. 我们要实现的进度条用
#来进行加载;
2. 后面要有数据来表示现在加载的进度是多少(百分数);
3. 最后用一个动态旋转的类⚪来表示程序还在继续加载。
👨💻实现思路
1. 动态加载的过程
动态加和之前的倒计时差不多,每次都要覆盖上次出现的
#,具体思路如下:
1. 定义一个字符类型数组char *str,用memset()函数进行初始化(‘\0’);
2. 循环100次,每次循环都在数组中加一个#,并打印str('\r’进行覆盖);
3. 强制冲刷缓冲区;
2. 进度加载
我们可以用每次循环的次数来当作是当前加载的进度,当然还要进行覆盖,具体思路如下:
1. 每次循环都以当前的循环次数作为加载进度;
2. 每次覆盖上一次的进度;
3. 强制冲刷缓冲区。
4. 程序休眠(可以用usleep()函数,单位是微秒)
3. 动态旋转
定义一个数组,并初始化为
-\\/-,覆盖的方法和之前类似,就不详细说了。
👨💻具体代码实现
#include "process_bar.h"
#include <memory.h>
#include <unistd.h>
#define style '#'
#define round "-\\/-"
void test()
{int i = 0;char str[100];memset(str,'\0',sizeof(str));while (i <= 100){str[i] = style;printf("[%-100s][%d%%][%c]\r",str,i,round[i % 4]);fflush(stdout);++i;usleep(10000);}printf("\n");
}

👨💻第二版本
我们正常用进度条肯定不是单独使用的,会结合其他的场景,例如下载界面,登陆界面。
对于要下载的文件,肯定有文件大小,下载的时候网络也有它的带宽,所以在下载的时候,每次下载的大小都是一个带宽,我们可以先写一个下载的函数:
download函数:
void download()
{double bandwidth = 1024 * 1024 * 1.0;double filesize = 1024 * 1024 * 10.0;double cur = 0.0;while (cur <= filesize){// 调用进度条函数test(filesize, cur);// 每次增加带宽cur += bandwidth;usleep(20000);}printf("\n");printf("this file has been downloaded\n");
}
进度条函数:
void test(double total, double current)
{char str[101];memset(str,'\0',sizeof(str));int i = 0;// 这次的比率double rate = (current * 100) / total;// 循环次数int loop_count = (int)rate;while (i <= loop_count){str[i++] = style; }printf("[%-100s][%.1lf%%][%c]\r",str,rate,round[loop_count % 4]);fflush(stdout);
}
回调函数版本(完整):
// 头文件 process_bar.h
#include <stdio.h>typedef void(*callback_t)(double, double);// 函数指针(回调函数)void test(double total, double current);// 函数实现文件 process_bar.c
#include "process_bar.h"
#include <memory.h>
#include <unistd.h>
#define style '#'
#define round "-\\/-"void test(double total, double current)
{char str[101];memset(str,'\0',sizeof(str));int i = 0;double rate = (current * 100) / total;int loop_count = (int)rate;while (i <= loop_count){str[i++] = style; }printf("[%-100s][%.1lf%%][%c]\r",str,rate,round[loop_count % 4]);fflush(stdout);
}// main.c 主函数和 download 函数
#include "process_bar.h"
#include <unistd.h>double bandwidth = 1024 * 1024 * 1.0;
void download(double filesize, callback_t cb)
{double cur = 0.0;while (cur <= filesize){cb(filesize, cur);cur += bandwidth;usleep(20000);}printf("\n");printf("this file has been downloaded\n");
}int main()
{download(1024*1024*100.0,test);download(1024*1024*20.0,test);return 0;
}

相关文章:
【Linux】简易进度条的实现
🎉博主首页: 有趣的中国人 🎉专栏首页: Linux 🎉其它专栏: C初阶 | C进阶 | 初阶数据结构 小伙伴们大家好,本片文章将会讲解Linux中进度条的实现的相关内容。 如果看到最后您觉得这篇文章写得…...
Docker + Django跨域解决方案
什么是Django Django 是一个开源的高级 Python Web 框架,它鼓励快速开发并遵循可重用和可维护的实践。Django 是在 MTV(模型-模板-视图)模式的基础上设计的,这个模式类似于但不同于 MVC(模型-视图-控制器)模…...
Maven 插件使用
1.spring-boot-maven-plugin 我们直接使用 maven package (maven自带的package打包功能),打包Jar包的时候,不会将该项目所依赖的Jar包一起打进去,在使用java -jar命令启动项目时会报错,项目无法正常启动。…...
【HMGD】GD32/STM32 DMA接收不定长串口数据
单片机型号:GD32F303系列 CubeMX配置 配置串口参数 开启DMA 开启中断 示例代码 使用到的变量 uint8_t RX_Buff_FLAG 0; uint8_t RX_Buff[300] {0}; uint8_t TX_Buff[300] {0};串口接收空闲函数 // 串口接收空闲函数 void HAL_UARTEx_RxEventCallback(UART_H…...
局域网手机端远程控制手机
局域网手机端远程控制手机 随着科技的进步和智能设备的普及,远程控制技术在日常生活与工作中的应用越来越广泛。其中,局域网内的手机端远程控制手机技术,因其便捷性和实用性,受到了众多用户的关注。本文将简要介绍该技术及其应用…...
如何在OpenWrt软路由中增加一个新功能
为了在OpenWrt中增加一个新的功能,并使其支持 UCI 配置,我们可以创建一个简单的C语言服务,例如一个简单的日志服务。此服务将记录到日志文件中,并支持通过 UCI 配置启用或禁用日志功能。以下是详细的步骤和代码示例。 1 创建服务…...
【linux】vmtouch文件缓存管理工具
目录 vmtouch简介 用法 例子 统计文件或者目录在缓存中的记录 缓存文件到内存 其他类似工具 vmtouch简介 vmtouch是用c语言编写的文件缓存管理工具,适用用于所有类Unix系统。 作用: 1,查看文件系统缓存情况 2,将文件或目…...
论文阅读:The Unreasonable Ineffectiveness of the Deeper Layers 层剪枝与模型嫁接的“双生花”
作者实证研究了针对流行的开放式预训练 LLM 系列的简单层修剪策略,发现在不同的 QA 基准上,直到去掉一大部分(最多一半)层(Transformer 架构)后,性能的下降才会降到最低。为了修剪这些模型&…...
Python批量备份华为设备配置到FTP服务器
Excel表格存放交换机信息: 备份文件夹效果图: Windows系统配置计划任务定时执行python脚本: Program/script:C:\Python\python.exe Add arguments (optional): D:\Python_PycharmProjects\JunLan_pythonProje…...
Java虚拟机(JVM)中确保资源及时释放的策略
在Java虚拟机(JVM)中,内存管理主要是通过垃圾回收(Garbage Collection, GC)来自动处理的。Java开发者通常不需要(也不应该)显式地释放对象内存,因为JVM的垃圾回收器会自动处理不再使…...
04-Fortran基础--Fortran数组和矩阵运算
04-Fortran基础--Fortran数组和矩阵运算 fortarn中对数组和矩阵的主要操作和内置运算包括: 数组的声明和初始化:fortarn中可以通过声明和初始化来创建数组。例如: integer :: my_array(3) [1, 2, 3] ! 声明一个包含3个整数的数组并初始化数…...
el-select选项框内容过长
利用popper-class实现选项框内容过长,截取显示功能: <el-select popper-class"popper-class" :popper-append-to-body"false" v-model"value" placeholder"请选择"><el-optionv-for"item in opt…...
K8S面试题学习5
参考K8S面试题(史上最全 持续更新)_kubernetes常见面试题-CSDN博客做的个人总结,规划是每天看10题,thx! 1. 请详述kube-proxy原理? 每个node节点都会运行一个kube-proxy的进程,核心功能是将service的访问…...
字符以及字符串函数
字符以及字符串函数 求字符串长度strlen 长度不受限制的字符串函数strcpystrcatstrcmp 长度受限制的字符串函数strncpystrncatstrncmp 字符串查找strstrstrtok 错误信息报告strerror 字符分类函数字符转换函数tolowertoupper 内存操作函数memcpymemmovememcmpmemset 这篇文章注…...
记录解决问题--redis ssl连接
1.问题场景 springboot连接redis启动报错,感觉是没连上redis,本地是正常启动的,但是本地不是ssl连接。 2.redis ssl连接知识 ①一般不开启ssl的连接,直接连接即可,有密码输密码。 ②不受信的ssl连接,也就…...
买卖股票的最佳时机
dp[i][0] 表示第i天持有股票所得最多现金,相当于买的价格最低,卖的价格最高 持有股票状态为0,不持有为1 用二维数组表示天数和是否持有, i-1天就持有,或者第i天买入 class Solution {public int maxProfit(int[] p…...
Linux部署安装
Linux部署安装 Linux中有两种软件安装包 一、源码包 软件的源代码是软件的原始数据,但是源代码不能直接在计算机中直接运行安装。 需要通过编译将源代码转换为计算机可以识别的机器语言,之后才可以进行安装。 源码包安装的方式可以在安装过程中发根据…...
docker搭建mysql集群实现主从复制
前言 随着业务的增长,一台数据服务器已经满足不了需求了,负载过重。这个时候就需要减压了,实现负载均衡和读写分离,一主一丛或一主多从。 主服务器只负责写,而从服务器只负责读,从而提高了效率减轻压力。 …...
Neo4j 之安装和 CQL 基本命令学习
正常使用结构化的查询语言 SQL(Structured Query Language)较多一些,但是像 Neo4j 这种非结构化的图形数据库来说,就不得不学习下 CQL(Cypher Query Language)语言了。如果你之前学过 《离散数学》或《图论…...
【全开源】JAVA台球助教台球教练多端系统源码支持微信小程序+微信公众号+H5+APP
功能介绍 球厅端:球厅认证、教练人数、教练的位置记录、助教申请、我的项目、签到记录、我的钱包、数据统计 教练端:我的页面,数据统计、订单详情、保证金、实名认证、服务管理、紧急求助、签到功能 用户端:精准分类、我的助教…...
Python数据库操作优化:从原理到实践
Python数据库操作优化:从原理到实践 1. 背景与动机 数据库操作是Web应用和数据处理系统的核心环节。优化数据库操作可以显著提升应用性能。本文将介绍Python数据库操作的优化技巧和最佳实践。 2. 核心原理 2.1 数据库性能瓶颈 网络延迟:应用与数据库的通…...
通达信数据接口Python化:量化投资数据获取的革命性方案
通达信数据接口Python化:量化投资数据获取的革命性方案 【免费下载链接】mootdx 通达信数据读取的一个简便使用封装 项目地址: https://gitcode.com/GitHub_Trending/mo/mootdx 还在为股票数据的获取而烦恼吗?传统的数据接口往往复杂难用…...
从RS232到112G SerDes:高速串行接口的‘逆袭’简史与FPGA工程师的生存指南
从RS232到112G SerDes:高速串行接口的技术革命与工程师转型指南 在数字通信领域,接口技术的演进犹如一场静默的革命。二十年前,工程师们还在为并行总线的布线复杂度和时钟偏移问题头疼不已;而今天,单通道112G PAM4 Ser…...
3个技巧让LibreTranslate翻译模型部署速度提升80%
3个技巧让LibreTranslate翻译模型部署速度提升80% 【免费下载链接】LibreTranslate Free and Open Source Machine Translation API. Self-hosted, offline capable and easy to setup. 项目地址: https://gitcode.com/GitHub_Trending/li/LibreTranslate LibreTranslat…...
Qwen3-Reranker-0.6B部署教程:对接Weaviate向量数据库Hybrid Search集成
Qwen3-Reranker-0.6B部署教程:对接Weaviate向量数据库Hybrid Search集成 你是不是也遇到过这样的问题?用向量数据库做检索,明明搜出来一堆结果,但排在前面的总感觉不是最想要的。传统的向量相似度搜索,有时候就是差那…...
Keil4 STC15浮点运算踩坑实录:如何避免数据类型转换导致的诡异错误
Keil4 STC15浮点运算避坑指南:从原理到实战的数据类型陷阱解析 在嵌入式开发领域,STC15系列单片机凭借其优异的性价比和丰富的功能接口,成为许多中小型项目的首选。然而当开发者使用Keil4这一经典但略显陈旧的开发环境时,常常会遇…...
深入解析DDR内存训练:从FLY BY布线到信号对齐
1. 为什么DDR内存需要训练? 当你按下电脑开机键的那一刻,主板上的DDR内存就开始了一段奇妙的"热身运动"。这个热身过程专业术语叫做内存训练(Memory Training),它是确保内存稳定运行的关键步骤。想象一下&a…...
从仿真到AI数据集:一条龙搞定COMSOL+MATLAB+Python数据处理流水线
从仿真到AI数据集:COMSOLMATLABPython全流程自动化实践 在物理仿真与机器学习融合的研究中,最耗时的往往不是算法设计,而是高质量数据集的构建。想象一下这样的场景:你需要在数百组参数组合下运行电磁场仿真,每次仿真生…...
Cardano节点高级功能探索:质押池、智能合约与治理的终极指南
Cardano节点高级功能探索:质押池、智能合约与治理的终极指南 【免费下载链接】cardano-node The core component that is used to participate in a Cardano decentralised blockchain. 项目地址: https://gitcode.com/gh_mirrors/ca/cardano-node Cardano节…...
移动热源坐标参数
comsol激光熔覆仿真模型,热流耦合,包含马兰戈尼非等温模激光熔覆工艺仿真里有个特有意思的物理现象——熔池表面会出现类似水波纹的流动轨迹。这可不是普通的热胀冷缩,而是马兰戈尼效应在金属熔液里跳"物理芭蕾"。咱们今天就用COMS…...

