一、进度条实现的核心原理


在 Linux 终端中实现进度条,本质是利用终端输出控制符和输出缓冲区刷新机制,让文本在同一行反复刷新,形成 “动态进度” 的视觉效果。


1.1 核心控制符


\r(回车符 Carriage Return):将光标移动到当前行的行首,不换行。后续输出会覆盖该行原有内容,这是实现单行刷新的核心。
\n(换行符 Line Feed):光标移动到下一行,进度条刷新过程中禁止使用,否则会逐行输出。


1.2 输出缓冲区机制


C/C++ 标准输出 stdout 默认是行缓冲模式:只有遇到换行符 \n、缓冲区满或程序结束时,才会真正把内容打印到终端。
因此每次刷新进度条后,必须手动刷新缓冲区:
C 风格:fflush(stdout)
C++ 风格:std::cout << std::flush


1.3 延时模拟


进度条通常配合任务进度使用,演示时用延时函数模拟任务耗时:
usleep(微秒):Linux 系统函数,单位微秒(1 秒 = 1000000 微秒),头文件 <unistd.h>
sleep(秒):单位秒,精度较低


二、版本 1:最简百分比进度条

仅显示百分比数字,适合入门理解核心逻辑。

#include <iostream>
#include <unistd.h>  // usleep

int main() {
    // 模拟100%进度
    for (int i = 0; i <= 100; ++i) {
        // \r 回到行首,覆盖输出
        printf("\r进度: %d%%", i);
        // 刷新缓冲区,立即显示
        fflush(stdout);
        // 延时50毫秒,模拟任务执行
        usleep(50000);
    }
    // 进度完成后换行,避免后续输出覆盖进度条
    printf("\n");
    return 0;
}

编译运行:

g++ progress1.cpp -o progress1
./progress1

三、版本 2:带填充条的基础进度条

在百分比基础上增加条形填充,视觉效果更直观,形如 [======> ] 50%。

#include <iostream>
#include <unistd.h>

#define BAR_LENGTH 50  // 进度条总长度(字符数)

int main() {
    for (int i = 0; i <= 100; ++i) {
        // 计算已填充的字符数
        int fill_len = i * BAR_LENGTH / 100;

        // 输出进度条框架
        printf("\r[");
        // 输出已填充部分
        for (int j = 0; j < fill_len; ++j) {
            printf("=");
        }
        // 输出箭头指示符
        if (fill_len < BAR_LENGTH) {
            printf(">");
        }
        // 输出空白部分
        for (int j = fill_len + 1; j < BAR_LENGTH; ++j) {
            printf(" ");
        }
        // 输出百分比
        printf("] %3d%%", i);

        fflush(stdout);
        usleep(50000);
    }
    printf("\n");
    return 0;
}

代码说明:
1.BAR_LENGTH 控制进度条在终端中占用的字符宽度,可根据终端大小调整。
2.进度比例与填充长度通过线性换算:填充长度 = 当前进度 * 总长度 / 100。
3.箭头 > 仅在未完成时显示,完成后整条都是 =,视觉更完整。

四、版本 3:C++ 风格实现(cout 版本)

使用 C++ 标准库 iostream 实现,更符合 C++ 编程习惯。

#include <iostream>
#include <unistd.h>

const int BAR_LEN = 50;

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

        // \r 回到行首
        std::cout << "\r[";
        for (int j = 0; j < fill; ++j) {
            std::cout << "=";
        }
        if (fill < BAR_LEN) {
            std::cout << ">";
        }
        for (int j = fill + 1; j < BAR_LEN; ++j) {
            std::cout << " ";
        }
        std::cout << "] " << i << "%";

        // C++ 刷新缓冲区
        std::cout.flush();
        usleep(50000);
    }
    std::cout << std::endl;
    return 0;
}

五、核心知识点总结


1.单行刷新的灵魂是 \r:它只回车不换行,让光标回到行首覆盖输出。
2.必须手动刷新缓冲区:没有 \n 时系统不会自动刷新,进度条会卡住不动。
3.进度条结束必须换行:否则终端下一行提示符会覆盖在进度条末尾。
4.以上实现均兼容所有 Linux 终端(bash、zsh、xterm 等),无额外依赖。

谢谢
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐