跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C算法

Linux 终端动态进度条实现:原理、编码与优化

Linux 终端动态进度条实现涉及回车符控制、缓冲区刷新及 ANSI 颜色码应用。通过 \r 字符实现光标回退覆盖,配合 fflush 强制输出,解决显示延迟问题。代码采用模块化设计,分离头文件与逻辑实现,支持彩色显示与速度统计。Makefile 自动化构建简化编译流程。掌握缓冲区机制与终端控制序列后,可灵活扩展至倒计时、日志滚动等交互场景,提升命令行工具的用户体验。

dehua dong发布于 2026/3/16更新于 2026/7/2434 浏览
Linux 终端动态进度条实现:原理、编码与优化

Linux 终端动态进度条实现:原理、编码与优化

在 Linux 开发中,进度条是最基础也最实用的系统程序之一。无论是文件下载、编译构建还是数据处理,一个直观的动态进度条能极大提升用户体验。看似简单的进度条,背后藏着行缓冲区、回车换行区别、字符刷新等关键知识点。

核心预备知识

在动手写代码前,必须先理清 3 个关键概念,否则容易出现'进度条不刷新'或'换行错乱'等问题。

1. 回车(\r)与换行(\n)的本质区别

  • 换行(\n):光标移动到下一行的行首,但不会回到当前行开头。
  • 回车(\r):光标回到当前行的行首,但不会移动到下一行。
  • 核心逻辑:进度条的核心是'在同一行反复覆盖刷新',因此必须用 \r 让光标回到行首,再重新打印新的进度信息。

2. 深入理解行缓冲区运行机制

C 语言的 printf 函数默认是'行缓冲'。只有遇到 \n、缓冲区满或手动刷新(fflush(stdout))时,才会把缓冲区的内容输出到终端。

如果只写 printf 而不加 \n 或 fflush,内容会一直存在缓冲区,终端看不到任何输出。这就是很多人写进度条'没反应'的原因。

注意:虽然没显示出来,但是 C 语言默认是顺序结构的,一定是先执行 printf 再执行 sleep 的。

修正示例:

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

int main() {
    printf("hello bite!");
    fflush(stdout);
    sleep(3);
    return 0;
}

练手倒计时小程序:

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

int main() {
    int cnt = 10;
    for (; cnt >= 0; cnt--) {
        (, cnt); 
        fflush();
        sleep();
    }
    ();
     ;
}
printf
"倒计时:% -2d\r"
// 注意格式控制
stdout
1
printf
"\n"
return
0

3. 进度条的核心构成元素

一个完整的动态进度条通常包含以下部分:

  • 进度条主体:用 = 等字符填充,直观显示完成比例。
  • 百分比:显示完成进度(0%~100%)。
  • 动态光标:用 |/-\ 循环切换,提示程序正在运行。
  • 附加信息:如当前进度 / 总进度、传输速度,提升实用性。

实战开发:打造动态彩色进度条

基于基础框架,我们会逐步优化实现出'彩色区分 + 速度显示 + 多场景适配'的进度条,核心分为头文件、实现文件、主函数三部分。

1. 基础版进度条模拟实现

这个版本主要演示原理,实际应用较少。

#include "process.h"
#include <string.h>
#include <unistd.h>

#define NUM 101
#define STYLE '='

// version1
void process_v1() {
    char buffer[NUM];
    memset(buffer, '\0', sizeof(buffer));
    const char* lable = "|/-\\";
    int len = strlen(lable);
    int cnt = 0;
    while (cnt <= 100) {
        printf("[%-100s][%d%%][%c]\r", buffer, cnt, lable[cnt % len]);
        fflush(stdout);
        buffer[cnt] = STYLE;
        cnt++;
        usleep(50000);
    }
    printf("\n");
}

2. 自动化构建流程:Makefile 编写

为了方便编译和清理,编写 Makefile 实现自动化构建,只需一条命令即可生成可执行文件。

Bin=process_bar
Cc=gcc
Src=$(wildcard *.c)
Obj=$(Src:.c=.o)

$(Bin):$(Obj)
	@echo "$^ link to $@"
	@$(Cc)-o$@ $^

%.o:%.c
	@echo "compiling $< to $@"
	@$(Cc)-c $<

.PHONY:clean
clean:
	@echo "File cleanup complete"
	@rm -f $(Obj) $(Bin)

.PHONY:debug
debug:
	@echo "Bin: $(Bin)"
	@echo "Cc: $(Cc)"
	@echo "Src: $(Src)"
	@echo "Obj: $(Obj)"

3. 头文件设计(process.h)

定义进度条回调函数类型和核心接口,方便后续扩展和复用。

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

// 定义进度条回调函数类型:适配不同场景的进度刷新逻辑
typedef void (*flush_t)(double total, double current, double speed, const char* userinfo);

// 彩色动态进度条核心接口
// total:总进度(如文件总大小)
// current:当前进度(如已下载大小)
// speed:当前速度(如 MB/s)
// userinfo:附加信息(如单位)
void Process_version(double total, double current, double speed, const char* userinfo);

4. 核心实现文件(process.c)

集成颜色控制、进度计算、动态刷新,是进度条的核心。

#include "process.h"
#include <string.h>

// 进度条配置参数
#define SIZE 103 // 进度条缓冲区大小(适配 100%+额外字符)
#define LABEL '=' // 进度填充字符

// ANSI 颜色码定义
#define COLOR_GREEN "\033[32m"
#define COLOR_GRAY "\033[90m"
#define COLOR_CYAN "\033[36m"
#define COLOR_RESET "\033[0m"
#define COLOR_RED "\033[31m"
#define COLOR_YELLOW "\033[33m"
#define COLOR_BLUE "\033[34m"
#define COLOR_MAGENTA "\033[35m"
#define COLOR_WHITE "\033[97m"
#define COLOR_BLACK "\033[30m"

// 彩色动态进度条实现
void Process_version(double total, double current, double speed, const char* userinfo) {
    // 边界处理:当前进度超过总进度时直接返回
    if (current > total) {
        return;
    }

    // 动态光标:循环切换,提示程序运行中
    static const char* lable = "|/-\\";
    static int index = 0; // 静态变量,记录光标位置,避免每次重置
    int size = strlen(lable);

    // 1. 计算比率
    double rate = current * 100.0 / total;
    char out_bar[SIZE];
    memset(out_bar, '\0', sizeof(out_bar));

    // 2. 填充进度字符
    int i = 0;
    for (; i < (int)rate; i++) {
        out_bar[i] = LABEL;
    }

    // 3. 彩色打印进度条(分颜色区分不同部分,视觉更清晰)
    printf(COLOR_RED "[%-100s]", out_bar); // 进度主体(红色)
    printf(COLOR_BLUE "[%5.1lf%%]", rate); // 百分比(蓝色)
    printf(COLOR_CYAN "[%c]", lable[index]); // 动态光标(青色)
    printf(COLOR_YELLOW "| %.1lf/%.1lf,speed: %.1lf%s\r", current, total, speed, userinfo); // 附加信息(黄色)
    printf(COLOR_RESET); // 重置颜色,避免污染后续输出

    // 手动刷新缓冲区,确保内容实时显示
    fflush(stdout);

    // 更新光标索引(循环切换)
    index++;
    index %= size;

    // 4. 进度条完成,换行
    if (current >= total) {
        printf("\r\n");
    }
}

5. 主函数模块(main.c)

模拟多场景下载任务,测试进度条的适配性和稳定性。

#include "process.h"
#include <unistd.h>
#include <stdlib.h>
#include <time.h>

// 全局配置(可根据实际场景修改)
double gtotal = 1024.0; // 默认总进度(如 1024MB)
double gspeed = 1.0;    // 默认速度

// 模拟下载任务:调用进度条回调函数刷新进度
void Download(double total, flush_t cb) {
    double current = 0.0;
    // 模拟不同网络速度(模拟实际场景中速度波动)
    double level[] = {0.01, 0.05, 10.0, 20.0, 24.0, 38.0, 50.0, 68.9};
    int num = sizeof(level) / sizeof(level[0]);

    while (1) {
        // 模拟下载耗时(1 秒刷新一次)
        usleep(1000000);

        // 随机选择当前速度(模拟网络波动)
        double speed = level[rand() % num];
        current += speed;

        // 边界处理:进度达到 100% 时终止
        if (current >= total) {
            current = total; // 确保进度不超过 100%
            cb(total, current, speed, "MB/s");
            break;
        } else {
            // 刷新进度条
            cb(total, current, speed, "MB/s");
        }
    }
}

int main() {
    // 初始化随机数种子,模拟速度波动
    srand(time(NULL));

    // 测试 4 个不同大小的下载任务,验证进度条适配性
    printf("download: \n");
    Download(gtotal, Process_version);
    printf("download: \n");
    Download(102.0, Process_version);
    printf("download: \n");
    Download(110.9, Process_version);
    printf("download: \n");
    Download(900.0, Process_version);

    return 0;
}

操作实践与效果展示

实际操作过程:

[Lotso@VM-4-4-centos lesson12--Progress]$ ll
total 16
-rw-rw-r-- 1 Lotso Lotso 1620 Nov 28 10:27 main.c
-rw-rw-r-- 1 Lotso Lotso 344 Nov 28 08:55 Makefile
-rw-rw-r-- 1 Lotso Lotso 3078 Nov 28 10:22 process.c
-rw-rw-r-- 1 Lotso Lotso 533 Nov 28 10:22 process.h

[Lotso@VM-4-4-centos lesson12--Progress]$ make
compiling main.c to main.o
compiling process.c to process.o
main.o process.o link to process_bar

[Lotso@VM-4-4-centos lesson12--Progress]$ ./process_bar
download: [====================================================================================================][100.0%][|]|1024.0/1024.0,speed: 24.0MB/s
download: [====================================================================================================][100.0%][\]|102.0/102.0,speed: 50.0MB/s
download: [====================================================================================================][100.0%][-]|110.9/110.9,speed: 68.9MB/s
download: [====================================================================================================][100.0%][/]|900.0/900.0,speed: 24.0MB/s

[Lotso@VM-4-4-centos lesson12--Progress]$ make clean
File cleanup complete

执行 ./process_bar 后,终端会输出 4 个下载任务的进度条,每个部分颜色区分清晰:

  • 红色:进度主体(= 填充部分);
  • 蓝色:百分比(如 50.0%);
  • 青色:动态光标(|/-\ 循环切换);
  • 黄色:附加信息(当前进度 / 总进度、传输速度);

进度完成后自动换行,后续任务不重叠,整体流畅无错乱。

注意:其中动态光标只与调用的这个函数有关,不管进度条动不动,它都是得转动的。如果大家想再优化一下的话,可以试着把 = 替换成色块,这样会更加清晰,其它的优化大家可以自己想想尝试一下。

结语

一个高质量的进度条,不仅是功能的补充,更是用户体验的提升。本文从基础原理到实战开发,再到优化扩展,带你吃透 Linux 终端进度条的核心逻辑。实现的彩色动态进度条可直接复用在下载、编译、数据处理等场景。掌握行缓冲区、回车换行、ANSI 颜色码等知识点后,你还可以举一反三,开发出更多终端交互工具(如倒计时、进度百分比动画)。Linux 终端开发的魅力就在于此——看似简单的功能,背后藏着扎实的底层逻辑,吃透这些细节,才能写出更稳定、更优雅的代码。

目录

  1. Linux 终端动态进度条实现:原理、编码与优化
  2. 核心预备知识
  3. 1. 回车(\r)与换行(\n)的本质区别
  4. 2. 深入理解行缓冲区运行机制
  5. 3. 进度条的核心构成元素
  6. 实战开发:打造动态彩色进度条
  7. 1. 基础版进度条模拟实现
  8. 2. 自动化构建流程:Makefile 编写
  9. 3. 头文件设计(process.h)
  10. 4. 核心实现文件(process.c)
  11. 5. 主函数模块(main.c)
  12. 操作实践与效果展示
  13. 结语
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 边缘计算设备部署轻量 TensorFlow 模型全流程
  • 玄武 CLI:国产芯片本地大模型部署工具详解
  • 6 款主流 AI 检测降重工具实测对比与选择建议
  • OpenClaw Skills 合集开源:700+ 本地 AI Agent 技能插件盘点
  • RISC-V 开源处理器实战:从 Verilog RTL 设计到 FPGA 原型验证
  • Atlas 数据中间件架构与核心特性介绍
  • VS Code 前端开发高效插件推荐与配置实战
  • Python 实现手机号归属地查询工具
  • 深度拆解美团闪购 AIGC 营销案例:技术如何赋能品牌叙事
  • AIGC Bar API 平台接入与工程化实践指南
  • C++ 模板进阶:非类型参数、特化与分离编译详解
  • Python 数据统计实战指南:从环境配置到高级分析
  • Dify 工作流集成 TTS:低代码实现语音输出
  • React Native 集成开源鸿蒙应用:WebView 桥接与原生模块方案
  • LLaMaFactory 基于魔搭社区免费 GPU 微调大模型实战
  • 小爱音乐 Docker 部署手册
  • 通义千问插件在 IDEA 中的 Java 开发实战应用
  • Stable Diffusion 本地模型 base_model 路径配置与加载指南
  • WebView 技术详解:原理、场景与性能安全挑战
  • WorkBuddy 接入 QQ 机器人配置指南

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online