Linux C++ 进度条进阶美化与工程化封装

一、ANSI 转义序列:终端色彩与光标控制

Linux 终端支持 ANSI 转义序列,可以实现文字着色、光标移动、清除行等高级效果,是美化进度条的基础。

1.1 常用颜色码(前景色)
颜色 代码 颜色 代码
黑色 30 红色 31
绿色 32 黄色 33
蓝色 34 紫色 35
青色 36 白色 37
1.2 常用光标 / 清屏控制
  • \033[K:清除光标位置到行尾的内容
  • \033[2K:清除整行内容
  • \033[nA:光标向上移动 n 行
  • \033[nB:光标向下移动 n 行

二、版本 4:彩色动态进度条

加入绿色进度条、百分比高亮、完成后变色提示,视觉效果大幅提升。

cpp 复制代码
#include <iostream>
#include <unistd.h>
#include <string>

const int BAR_LEN = 50;

// ANSI 颜色宏
#define COLOR_GREEN  "\033[32m"
#define COLOR_YELLOW "\033[33m"
#define COLOR_RED    "\033[31m"
#define COLOR_RESET  "\033[0m"

int main() {
    for (int i = 0; i <= 100; ++i) {
        int fill = i * BAR_LEN / 100;

        std::cout << "\r" COLOR_GREEN "[";
        // 填充部分用绿色
        for (int j = 0; j < fill; ++j) {
            std::cout << "=";
        }
        // 箭头用黄色
        if (fill < BAR_LEN) {
            std::cout << COLOR_YELLOW ">";
        }
        // 空白部分重置颜色
        std::cout << COLOR_RESET;
        for (int j = fill + 1; j < BAR_LEN; ++j) {
            std::cout << " ";
        }

        // 百分比数字高亮
        if (i == 100) {
            std::cout << COLOR_GREEN "] " << i << "% 完成" COLOR_RESET;
        } else {
            std::cout << "] " COLOR_YELLOW << i << "%" COLOR_RESET;
        }

        std::cout.flush();
        usleep(40000);
    }
    std::cout << std::endl;
    return 0;
}

三、版本 5:带速度与剩余时间估算的进度条

模拟真实任务场景,加入已处理量 / 总量、处理速度、预计剩余时间(ETA),是工程中最实用的版本。

cpp 复制代码
#include <iostream>
#include <unistd.h>
#include <time.h>
#include <string>

const int BAR_LEN = 40;
#define COLOR_GREEN  "\033[32m"
#define COLOR_YELLOW "\033[33m"
#define COLOR_CYAN   "\033[36m"
#define COLOR_RESET  "\033[0m"

int main() {
    const int total = 200;  // 模拟总任务量
    time_t start_time = time(NULL);

    for (int i = 0; i <= total; ++i) {
        // 计算进度百分比
        double percent = (double)i / total * 100;
        int fill = (int)(percent * BAR_LEN / 100);

        // 计算速度和剩余时间
        time_t now = time(NULL);
        double elapsed = difftime(now, start_time);
        double speed = (elapsed > 0) ? (i / elapsed) : 0;
        int eta = (speed > 0) ? (int)((total - i) / speed) : 0;

        // 输出进度条
        printf("\r" COLOR_GREEN "[" COLOR_RESET);
        for (int j = 0; j < fill; ++j) printf("=");
        if (fill < BAR_LEN) printf(COLOR_YELLOW ">" COLOR_RESET);
        for (int j = fill + 1; j < BAR_LEN; ++j) printf(" ");
        printf("] ");

        // 输出详细信息:百分比、已完成/总量、速度、剩余时间
        printf(COLOR_YELLOW "%5.1f%%" COLOR_RESET "  ", percent);
        printf("%d/%d  ", i, total);
        printf(COLOR_CYAN "%.1f 个/秒" COLOR_RESET "  ", speed);
        printf("剩余: %d秒", eta);

        fflush(stdout);
        usleep(30000);  // 模拟每个任务单元的耗时
    }
    printf("\n");
    return 0;
}
实现逻辑说明
  1. 速度计算速度 = 已完成数量 / 已用时间
  2. 剩余时间估算ETA = (总量 - 已完成量) / 速度
  3. 使用 time() 函数获取系统时间,difftime() 计算时间差,单位为秒。
  4. 适合文件下载、批量处理、数据导入等真实业务场景。

四、版本 6:C++ 类封装工程版

将进度条封装为 ProgressBar 类,支持自定义样式、颜色、总长度,可直接嵌入项目复用

cpp 复制代码
#ifndef PROGRESS_BAR_H
#define PROGRESS_BAR_H

#include <string>
#include <time.h>

class ProgressBar {
public:
    // 构造函数:总任务量、进度条宽度、样式字符
    ProgressBar(int total, int width = 50, char fill_char = '=', char arrow_char = '>');

    // 更新进度:传入当前已完成量
    void update(int current);

    // 手动设置完成并换行
    void finish();

    // 是否已经完成
    bool is_finished() const { return finished_; }

private:
    int total_;       // 总任务量
    int width_;       // 进度条宽度
    char fill_char_;  // 填充字符
    char arrow_char_; // 箭头字符
    int current_;     // 当前完成量
    bool finished_;   // 是否完成
    time_t start_;    // 开始时间

    // 格式化时间显示
    std::string format_time(int seconds) const;
};

#endif
cpp 复制代码
#ifndef PROGRESS_BAR_H
#define PROGRESS_BAR_H

#include <string>
#include <time.h>

class ProgressBar {
public:
    // 构造函数:总任务量、进度条宽度、样式字符
    ProgressBar(int total, int width = 50, char fill_char = '=', char arrow_char = '>');

    // 更新进度:传入当前已完成量
    void update(int current);

    // 手动设置完成并换行
    void finish();

    // 是否已经完成
    bool is_finished() const { return finished_; }

private:
    int total_;       // 总任务量
    int width_;       // 进度条宽度
    char fill_char_;  // 填充字符
    char arrow_char_; // 箭头字符
    int current_;     // 当前完成量
    bool finished_;   // 是否完成
    time_t start_;    // 开始时间

    // 格式化时间显示
    std::string format_time(int seconds) const;
};

#endif

使用示例 main.cpp

cpp 复制代码
#include "progress_bar.h"
#include <unistd.h>

int main() {
    const int TOTAL = 500;
    ProgressBar bar(TOTAL, 60, '#', '>');

    for (int i = 0; i <= TOTAL; ++i) {
        bar.update(i);
        usleep(10000);
    }
    return 0;
}

编译运行:

cpp 复制代码
g++ main.cpp progress_bar.cpp -o progress_bar
./progress_bar

五、进阶扩展:旋转等待指示器

当任务总量未知、只能显示 "正在运行" 时,使用旋转字符动画(| / - \)替代进度条。

cpp 复制代码
#include <iostream>
#include <unistd.h>

int main() {
    const char spinner[] = {'|', '/', '-', '\\'};
    int idx = 0;

    std::cout << "正在处理中... ";
    for (int i = 0; i < 30; ++i) {  // 模拟30次循环
        printf("\b%c", spinner[idx % 4]);
        fflush(stdout);
        idx++;
        usleep(150000);
    }
    printf("\b完成\n");
    return 0;
}

六、核心总结与注意事项

  1. ANSI 转义序列是 Linux 终端美化的核心,所有主流终端均兼容。
  2. 工程化使用时建议封装为类,支持自定义样式、自动计算速度与 ETA。
  3. 总量未知场景可用旋转指示器替代固定进度条。
  4. 注意事项:
    • 重定向输出到文件时,ANSI 颜色码会变成乱码,生产环境可加判断禁用颜色。
    • 进度更新不要过于频繁(比如每毫秒刷新一次),避免占用过多 CPU。
    • 多线程环境下使用进度条需要加锁,防止输出错乱。

谢谢

相关推荐
M78佐菲3 小时前
Linux学习笔记:TCP协议
linux·笔记·学习·tcp/ip·算法
Brilliantwxx3 小时前
【Linux】 进程(9)程序与进程地址空间(基础+进阶+面试题)
linux·运维·服务器·开发语言·c++
不怕犯错,就怕不做4 小时前
git prune 自动删除本地记录中那些远程已经不存在的分支引用
linux·服务器·git
richdata4 小时前
商品数字化不是先做大数据,而是先把数据变成可用决策
大数据·运维·数据治理·商品数字化·智能补货·ai商品决策
weixin_416667965 小时前
【无标题】
运维·服务器·网络
一池秋_5 小时前
arm低配linux设备,桌面应用冷启动提速方法
linux·运维·arm开发
惜离殇6 小时前
从零开始的敲代码生活--Linux应用软件(文件操作基础1)
linux·c语言·文件操作·标准io
上海云盾-小余7 小时前
流量攻击复盘:为什么 WAF 完好,业务依旧瘫痪
运维·服务器·网络
IT大白鼠7 小时前
Docker 私有仓库管理:Harbor 企业级仓库搭建与镜像全生命周期管理
运维·docker·容器
戴西软件7 小时前
戴西iDWS.3DViz Suite数据轻量化可视化软件,从传统桌面软件向云端协同的重大突破
大数据·运维·网络·人工智能·机器学习·3d