Linux 编程第一个小程序:进度条

🎯 进度条实现原理

1. 回车换行的关键区别

Plain 复制代码
printf("\r倒计时: %2d", count);  // \r 回车:回到行首不换行
printf("\n换行测试");            // \n 换行:移到下一行

重要区别

  • \r(回车):光标回到当前行的开头,不换到新行

  • \n(换行):光标移动到下一行,位置不变

  • 历史渊源:早期打字机时代,回车是让打字头回到行首,换行是转动滚筒到下一行



2. 缓冲区刷新机制

Plain 复制代码
printf(LIGHT_GREEN "[%-100s][%d%%][%c]" NONE "\r", bar, rate, lable[rate % len]);
fflush(stdout);  // 强制立即显示

为什么需要 fflush

C语言输出默认使用缓冲区,内容不会立即显示到屏幕。fflush(stdout) 强制清空缓冲区,确保进度条实时更新。

缓冲区类型

  • 全缓冲:文件操作通常使用

  • 行缓冲:终端输出,遇到换行符刷新

  • 无缓冲:标准错误流 stderr




📊 进度条代码分析

头文件定义 (processBar.h)

Plain 复制代码
#pragma once  // 防止头文件重复包含

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

/*-------------进度条颜色-------------*/
#define NONE            "\033[m"
#define LIGHT_GREEN     "\033[1;32m"
#define LIGHT_RED       "\033[1;31m"
#define LIGHT_BLUE      "\033[1;34m"
#define LIGHT_YELLOW    "\033[1;33m"
#define LIGHT_CYAN      "\033[1;36m"
#define LIGHT_PURPLE    "\033[1;35m"
#define LIGHT_WHITE     "\033[1;37m"

/*-------------进度条样式------------*/
#define NUM     102     // 缓冲区大小
#define TOP     100     // 进度最大值
#define BODY    '='     // 进度条主体
#define RIGHT   '>'     // 进度条头部

// 函数指针类型定义
typedef void (*callback_t)(int);

extern void InitBar();            // 初始化进度条
extern void ProcessBar(int rate); // 更新进度条


进度条核心实现 (processBar.c)

Plain 复制代码
#include "processBar.h"
#include <string.h>

const char *lable = "|/-\\";  // 旋转指示器
char bar[NUM];                // 进度条缓冲区

// 初始化进度条
void InitBar()
{
    memset(bar, '\0', sizeof(bar));
}

// 更新进度条显示
void ProcessBar(int rate)
{
    if(rate < 0 || rate > 100) return;

    int len = strlen(lable);
    
    // 根据进度选择颜色
    const char *color;
    if(rate < 30)
        color = LIGHT_RED;
    else if(rate < 70)
        color = LIGHT_YELLOW;
    else
        color = LIGHT_GREEN;
    
    // 使用颜色和格式化输出
    printf("%s[%-100s][%d%%][%c]" NONE "\r", color, bar, rate, lable[rate % len]);
    fflush(stdout);
    
    // 更新进度条内容
    bar[rate++] = BODY;
    if(rate < 100) bar[rate] = RIGHT;
}


下载模拟模块 (downLoad.h)

Plain 复制代码
#pragma once

#include "processBar.h"

// 下载函数声明
void DownLoad(callback_t cb);


下载模拟模块 (downLoad.c)

Plain 复制代码
#include "downLoad.h"
#include <unistd.h>

void DownLoad(callback_t cb)
{
    int total = 1024; // 总大小 1024MB
    int curr = 0;     // 当前进度 0MB
    
    while(curr <= total)
    {
        usleep(50000);              // 模拟下载耗时 50ms
        int rate = curr*100/total;  // 计算进度百分比
        cb(rate);                   // 回调函数更新进度条
        curr += 8;                  // 每次下载8MB
    }
    printf("\n下载完成!\n");  // 下载完成换行
}


主程序 (main.c)

Plain 复制代码
#include "downLoad.h"
#include <unistd.h>

int main()
{
    printf("开始执行多个下载任务...\n\n");
    
    printf(LIGHT_RED "任务一 下载中..." NONE "\n");
    DownLoad(ProcessBar);
    InitBar();  // 重置进度条
    sleep(1);   // 间隔1秒
    
    printf(LIGHT_BLUE "任务二 下载中..." NONE "\n");
    DownLoad(ProcessBar);
    InitBar();
    sleep(1);
    
    printf(LIGHT_PURPLE "任务三 下载中..." NONE "\n");
    DownLoad(ProcessBar);
    InitBar();

    printf(LIGHT_GREEN "所有任务执行完毕!" NONE "\n");
    return 0;
}



🔧 Makefile 构建配置

Plain 复制代码
CC = gcc
CFLAGS = -Wall -Wextra -std=c99
TARGET = processBar
SOURCES = processBar.c downLoad.c main.c
HEADERS = processBar.h downLoad.h

$(TARGET): $(SOURCES) $(HEADERS)
	$(CC) $(CFLAGS) $(SOURCES) -o $(TARGET)

# 调试版本
debug: CFLAGS += -g -DDEBUG
debug: $(TARGET)

# 发布版本
release: CFLAGS += -O2
release: $(TARGET)

.PHONY: clean install uninstall

clean:
	rm -f $(TARGET)

install: $(TARGET)
	sudo cp $(TARGET) /usr/local/bin/

uninstall:
	sudo rm -f /usr/local/bin/$(TARGET)



🎨 进度条设计亮点

1. 颜色系统

使用 ANSI 转义序列实现彩色输出:

  • \033[1;32m:亮绿色

  • \033[m:重置颜色

  • \033[1;31m:亮红色

  • \033[1;34m:亮蓝色

  • 颜色编码原理\033[ 是转义序列开始,1 表示粗体,32 表示绿色,m 结束



2. 旋转指示器

Plain 复制代码
const char *lable = "|/-\\";  // 旋转动画序列
lable[rate % len]             // 循环显示旋转字符

动画原理:通过模运算循环显示四个字符,创建旋转效果



3. 回调函数设计

Plain 复制代码
typedef void (*callback_t)(int);  // 函数指针类型
void DownLoad(callback_t cb);     // 接收回调函数

优势

  • 下载模块与显示模块解耦,便于复用和维护

  • 支持不同的进度显示方式

  • 符合开闭原则,易于扩展



4. 智能颜色切换

Plain 复制代码
if(rate < 30)
    color = LIGHT_RED;      // 进度低显示红色
else if(rate < 70)
    color = LIGHT_YELLOW;   // 进度中显示黄色
else
    color = LIGHT_GREEN;    // 进度高显示绿色



🚀 编译和运行

编译项目

Plain 复制代码
# 普通编译
make

# 调试版本
make debug

# 发布版本
make release


运行程序

Plain 复制代码
./processBar


安装到系统

Plain 复制代码
sudo make install


预期输出效果

Plain 复制代码
开始执行多个下载任务...

任务一 下载中...
[=================>][75%][/]
下载完成!

任务二 下载中...
[=============================>][95%][-]
下载完成!

任务三 下载中...
[==================================================][100%][|]
下载完成!

所有任务执行完毕!



🔍 扩展功能建议

1. 添加时间估算

C 复制代码
// 在 ProcessBar 函数中添加时间估算
static time_t start_time = 0;
if (start_time == 0) {
    start_time = time(NULL);
}
time_t current_time = time(NULL);
int elapsed = (int)(current_time - start_time);
int remaining = (elapsed * (100 - rate)) / (rate + 1);
printf("[%ds/%ds]", elapsed, remaining);


2. 支持多种样式

C 复制代码
// 进度条样式枚举
typedef enum {
    STYLE_CLASSIC,    // [====>]
    STYLE_PERCENT,    // 75%
    STYLE_SPINNER,    // ⣷
    STYLE_BLOCK       ███████
} ProgressStyle;


3. 网络下载集成

C 复制代码
// 实际下载功能集成
size_t write_callback(void *ptr, size_t size, size_t nmemb, void *userdata) {
    // 更新下载进度
    // 调用进度条回调
    return size * nmemb;
}


📦 项目结构总结

Plain 复制代码
progress_bar/
├── processBar.h      # 头文件定义
├── processBar.c      # 进度条核心实现
├── downLoad.h        # 下载模块头文件
├── downLoad.c        # 下载模拟实现
├── main.c           # 主程序入口
└── Makefile         # 构建配置

打包传送到本地

克隆到仓库

相关推荐
弘毅 失败的 mian1 小时前
Linux 基本工具详解
linux·运维·服务器·经验分享·笔记
摇滚侠1 小时前
零基础小白自学 Git_Github 教程,DeskTop 进阶操作,笔记12
笔记·git·github
stars-he1 小时前
单片机转换电路学习笔记
笔记·单片机·学习
小农民壞得狠丶1 小时前
白羊座讨厌这些 。。。。。。
经验分享
wadesir1 小时前
提升系统效率的关键(Linux文件系统性能优化入门教程)
linux·网络·性能优化
挽天java1 小时前
Arduino/EIDE/Platform IO/Linux/MRS/Keil/STM32Cubemx配置
linux·运维·stm32
2501_915918411 小时前
iOS 手机抓包软件怎么选?HTTPS 调试、TCP 数据流分析与多工具组合的完整实践
android·ios·智能手机·小程序·https·uni-app·iphone
金斗潼关1 小时前
Ubuntu搭建Vulhub漏洞靶场进行xstream的CVE-2021-21351漏洞利用
linux·ubuntu·java反序列化漏洞检测
猫天意1 小时前
【深度学习即插即用模块之注意力】EfficientChannelAttention,涨点必备彻底疯狂!
人工智能·笔记·深度学习·神经网络·yolo