printf("\r倒计时: %2d", count); // \r 回车:回到行首不换行
printf("\n换行测试"); // \n 换行:移到下一行重要区别:
\r(回车):光标回到当前行的开头,不换到新行
\n(换行):光标移动到下一行,位置不变
printf(LIGHT_GREEN "[%-100s][%d%%][%c]" NONE "\r", bar, rate, lable[rate % len]);
fflush(stdout); // 强制立即显示为什么需要 fflush?
C语言输出默认使用缓冲区,内容不会立即显示到屏幕。fflush(stdout) 强制清空缓冲区,确保进度条实时更新。
缓冲区类型:
#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); // 更新进度条#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;
}#pragma once
#include "processBar.h"
// 下载函数声明
void DownLoad(callback_t cb);#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"); // 下载完成换行
}#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;
}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)使用 ANSI 转义序列实现彩色输出:
\033[1;32m:亮绿色
\033[m:重置颜色
\033[1;31m:亮红色
\033[1;34m:亮蓝色
\033[ 是转义序列开始,1 表示粗体,32 表示绿色,m 结束
const char *lable = "|/-\\"; // 旋转动画序列
lable[rate % len] // 循环显示旋转字符动画原理:通过模运算循环显示四个字符,创建旋转效果
typedef void (*callback_t)(int); // 函数指针类型
void DownLoad(callback_t cb); // 接收回调函数优势:
if(rate < 30)
color = LIGHT_RED; // 进度低显示红色
else if(rate < 70)
color = LIGHT_YELLOW; // 进度中显示黄色
else
color = LIGHT_GREEN; // 进度高显示绿色# 普通编译
make
# 调试版本
make debug
# 发布版本
make release./processBarsudo make install开始执行多个下载任务...
任务一 下载中...
[=================>][75%][/]
下载完成!
任务二 下载中...
[=============================>][95%][-]
下载完成!
任务三 下载中...
[==================================================][100%][|]
下载完成!
所有任务执行完毕!// 在 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);// 进度条样式枚举
typedef enum {
STYLE_CLASSIC, // [====>]
STYLE_PERCENT, // 75%
STYLE_SPINNER, // ⣷
STYLE_BLOCK ███████
} ProgressStyle;// 实际下载功能集成
size_t write_callback(void *ptr, size_t size, size_t nmemb, void *userdata) {
// 更新下载进度
// 调用进度条回调
return size * nmemb;
}progress_bar/
├── processBar.h # 头文件定义
├── processBar.c # 进度条核心实现
├── downLoad.h # 下载模块头文件
├── downLoad.c # 下载模拟实现
├── main.c # 主程序入口
└── Makefile # 构建配置