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。
    • 多线程环境下使用进度条需要加锁,防止输出错乱。

谢谢

相关推荐
别动我齐刘海5 小时前
Linux 系统调试学习1
linux·运维·服务器·c++·学习·机器学习·机器人
Lsetea5 小时前
OpenSSL报certificate chain too long:error 22与verify_depth深度排查
linux·https·ssl证书·openssl·证书链
不像程序员的程序媛6 小时前
linux常见文本操作命令
linux·运维·服务器
wangbing11257 小时前
开发指南149-IotDB-常用命令
linux·运维·iotdb
Dovis(誓平步青云)7 小时前
常用命令藏得太深?怎么做一个快捷命令坞
运维·前端·自动化·音视频·prometheus
看着博客敲代码7 小时前
WorkBuddy 接上 Kali MCP 做自动化渗透:信息收集到初步验证的落地记录
linux·人工智能·安全·网络安全·自动化
志栋智能7 小时前
运维超自动化的知识管理与传承
运维·自动化
蜗牛互联网8 小时前
Python Agent工具调用的白名单、参数校验与审批门禁
java·服务器·前端·人工智能·后端·python
jack186898 小时前
OpenClaw 数据采集与自动化应用场景指南
运维·自动化
小HANN8 小时前
华为云企业网站上云实战|从零搭建高可用WordPress全站架构(ECS+RDS+ELB+弹性伸缩+云监控闭环)
linux·运维·服务器·经验分享