5 ~> Linux 中的第一个系统程序:进度条
5.1 两个储备知识:回车换行 / 缓冲区
5.1.1 回车和换行是一码事吗?
回车和换行不是一码事。
这是一张普通的作文纸,每次我们写完一行,都要从下一行开头开始继续往下写,写完一段,都要新起一行——
如下图,键盘、打字机上面都有回车键——
为什么说回车和换行不是一回事呢?
是的,回车换行是两个动作,\r 是回车,\n 是换行(和\r\n是一样的),在 C/C++ 里面\n(C)、std::endl(C++)是把两个动作(回车和换行)合写成一个了。
5.1.2 缓冲区
[Alice@VM-4-17-centos Ludy]$ vim code.c
[Alice@VM-4-17-centos Ludy]$ make 我要开始编译了...
code.c -> code.o 我要开始链接了...
code.o -> code.exe
[Alice@VM-4-17-centos Ludy]$ ./code.exe hello world!
[Alice@VM-4-17-centos Ludy]$
这里就是字符位数不够,右对齐了——

fflush(stdout); // 强制刷新缓冲区
5.2 观察:行缓冲区
下面的代码会有哪些现象?
#include <stdio.h>
int main(){
printf("hello Alice!\n");
sleep(3);
return 0;
}
#include <stdio.h>
int main(){
printf("hello Alice!");
sleep(3);
return 0;
}
#include <stdio.h>
int main(){
printf("hello Alice!");
fflush(stdout);
sleep(3);
return 0;
}
5.3 练练手:demo:光标快速回退,完成倒计时功能
5.3.1 代码演示

#include <stdio.h>
#include <unistd.h>
int main()
{
int cnt = 10;
for(;cnt >= 0;cnt--)
{
printf("倒计时:%-.2d\r",cnt); // 格式化输出
fflush(stdout); // 强制刷新缓存
sleep(1);
}
printf("\n");
return 0;
}
5.3.2 最终效果呈现
[Alice@VM-4-17-centos Ludy]$ make
[Alice@VM-4-17-centos Ludy]$ ./code.exe
倒计时:0
5.4 进度条(两种方式,这里只演示后一种)
进度条是用户界面中常见的元素,用于直观展示任务的完成进度。接下来介绍如何使用 C 语言在 Linux 操作系统中(centos 版本)实现一个功能完整的进度条。
5.4.1 Makefile
Bin=process_bar
Cc=gcc
Src=$(wildcard *.c)
Obj=$(Src:.c=.o)
$(Bin):$(Obj)
@echo "$^ link to $@"
@$(Cc) -o $@ $^
%.o:%.c
@echo "compling $< to $@"
@$(Cc) -c $<
.PHONY:clean
clean:
@echo "Clean Project...Done"
@rm -f $(Obj)$(Bin)
.PHONY:Print
Print:
@echo $(Bin)
@echo $(Cc)
@echo $(Src)
@echo $(Obj)
5.4.2 Process.h
定义函数指针类型
flush_t,支持回调机制。 声明进度条显示函数接口。
total - 总任务量:表示需要完成的全部工作量; current - 当前完成量:表示已经完成的工作量; speed - 当前速度:表示单位时间内完成的工作量; userinfo - 用户信息:这里表示速度单位:'MB/s'
#ifndef PROCESS_H
#define PROCESS_H
// ANSI 颜色代码
#define COLOR_RED "\033[31m"
#define COLOR_GREEN "\033[32m"
#define COLOR_YELLOW "\033[33m"
#define COLOR_BLUE "\033[34m"
#define COLOR_MAGENTA "\033[35m"
#define COLOR_CYAN "\033[36m"
#define COLOR_RESET "\033[0m"
typedef void (*flush_t)(double total,double current,double speed,const char* userinfo);
void Process(double total,double current,double speed,const char* userinfo);
#endif
5.4.3 Process.c
百分比计算:current * 100.0 / total进度条填充:使用循环填充-字符旋转光标:通过字符序列|\-/实现动画效果实时刷新:使用\r 回车符和 fflush(stdout) 实现原地更新
#include "process.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
// 如果头文件中没有定义颜色,则在这里定义
#ifndef COLOR_RED
#define COLOR_RED "\033[31m"
#define COLOR_GREEN "\033[32m"
#define COLOR_YELLOW "\033[33m"
#define COLOR_BLUE "\033[34m"
#define COLOR_MAGENTA "\033[35m"
#define COLOR_CYAN "\033[36m"
#define COLOR_RESET "\033[0m"
#endif
#define SIZE 100
#define LABEL '='
void Process(double total, double current, double speed, const char* userinfo)
{
if(current > total)
return;
// 旋转光标
static const char* lable = "|/-\\";
index = ;
size = (lable);
rate = current * / total;
out_bar[SIZE];
(out_bar, , (out_bar));
i = ;
bar_length = ()rate;
(bar_length > ) bar_length = ;
(; i < bar_length; i++)
{
out_bar[i] = LABEL;
}
* color;
(rate < )
color = COLOR_RED;
(rate < )
color = COLOR_YELLOW;
color = COLOR_GREEN;
(,
out_bar, rate, lable[index], current, total, speed, userinfo);
fflush();
index++;
index %= size;
(current >= total)
{
();
}
}
5.4.4 main.c
#include "process.h"
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
// 有一个下载任务
double gtotal = 1024.0; // 目标文件的总大小
double gspeed = 1.0; // 下载时的网络速度
// 回调函数
void Download(double total, flush_t cb)
{
double level[] = {0.5, 1.0, 2.0, 5.0, 10.0, 20.0, 30.0, 30.0, 40.5, 80.5};
int num = sizeof(level) / sizeof(level[0]);
double current = 0.0; // 当前下载了多少
while(1)
{
usleep(100000); // 模拟下载,单位微秒
double speed = level[rand()%num]; // 随机网速
current += speed;
if(current >= total)
{
current = total;
cb(total,current,speed,"MB/s"); // 更新进度条
;
}
{
cb(total,current,speed,);
}
}
}
{
srand(time());
();
Download(gtotal,Process);
();
Download(,Process);
();
Download(,Process);
();
Download(,Process);
();
Download(,Process);
;
}
5.5 数据流动示意图
初始化阶段 ↓ total = 1024.0(总任务量)
↓ 循环更新阶段 ↓ current = 0 → 逐渐增加 → total (当前进度)
speed = 随机值 (实时速度)
userinfo = "MB/s"(单位信息)
↓ 显示阶段 ↓
[----------][45.5%][\]|465.9/1024.0, speed:25.3MB/s
5.6 效果演示
5.6.1 静态效果

5.6.2 动态效果
进度条(无色版本)



