进度条小程序
GitHub地址
前言
在Linux系统编程中,控制台交互的视觉反馈是提升用户体验的重要环节。进度条作为经典的人机交互组件,在软件安装、文件传输、数据处理等场景中具有广泛应用价值。本文将以Linux环境下C语言实现的进度条程序为切入点,深入探讨控制台输出控制、缓冲区机制、函数指针应用等核心技术。通过三个版本迭代的代码解析(基础版/V1、模拟多任务版/V2),读者将掌握从原理到实践的完整知识链路。
前置知识
回车换行(CR/LF)的深度解析
在C语言中,我们使用\n来表示换行,这其实是C语言帮我们做了处理。实际上,回车和换行其实是两个动作。
C语言中用
\n来表示回车和换行。
以上图片深入阐述了回车和换行概念以及和区别。
-
\r:回车,光标回到当前行的最开始。C语言中用\r来表示仅回车。 -
\n:换行,光标垂直向下移动一行,叫做换行。
历史渊源与技术规范
- ASCII规范定义:
CR(Carriage Return,\r,ASCII 13)将光标移动到行首 -
LF(Line Feed,\n,ASCII 10)使光标下移一行 -
Windows系统采用CRLF组合实现新行操作 -
Linux/Unix系统使用LF单独完成换行
在进度条/倒计时中的应用
printf("%-3d\r", ***t); // 关键代码示例
此代码实现:
- 使用
%-3d保证3字符宽度左对齐- 3表示该值位宽为3,C语言默认为右对齐,用
-来表示左对齐。
- 3表示该值位宽为3,C语言默认为右对齐,用
-
\r使每次输出回到行首 - 配合
fflush(stdout)强制刷新缓冲区 - 实现原地更新的数字倒计时效果
缓冲区机制的全面剖析
缓冲区引入
先看如下两个例子:
- 有换行符
\n时显示器直接刷新
- 无换行符时,像是先执行了
sleep再执行printf
经分析得知: -
C语言中一定是按顺序执行代码的,因此一定是printf先执行,再执行sleep。 - 那么,在
sleep期间,printf函数一定已经执行完了。 - 那么,
sleep期间,hello wolrd在哪里?
综上,hello wolrd一定是被保存起来了!!!
保存hello wolrd,必然 需要一块内存空间,这块内存空间被称为缓冲区。
- 缓冲区就是由
C语言维护的一段内存。
C程序运行时,默认会帮助我们打开三个输入输出流
-
stdin:标准输入 -
stdout:标准输出(默认是显示器) -
stderr:标准错误
C语言的默认行为是在程序退出时,再刷新缓冲区。
printf打印消息,是向stdout输入,消息暂存在了stdout中,当我们不想让消息暂存在缓冲区中,而是想直接刷新stdout的内容到显示器时,可以使用fflush刷新,默认stdout在程序结束时刷新,使用fflush可以强制进行刷新输入输出流。
- 以下:
- 此时
printf("hello world")没有\n - 使用
fflush(stdout)强制将缓冲区中的数据刷新到显示器上
通过以上两个例子,我们已经对缓冲区有了一个大概的理解了。
缓冲类型对比
| 缓冲类型 | 特征 | 典型应用场景 |
|---|---|---|
| 全缓冲 | 缓冲区满时刷新 | 文件操作 |
| 行缓冲 | 遇到换行符或缓冲区满时刷新 | 终端输出(默认) |
| 无缓冲 | 立即输出 | 标准错误流stderr
|
进度条开发中的关键控制
- 手动刷新机制:
fflush(stdout); // 强制立即输出缓冲区内容
进度条实现
以小见大——倒计时
倒计时最终效果演示
- 代码如下:
void test() {
//实现一个倒计时
int ***t = 100;
while (***t >= 0) {
// printf("%-2d\r", ***t);//使用\r回车会导致三位数只刷新了两位数
printf("%-3d\r", ***t); // %3d\r 可以实现在行的开头更新数字 -相当于反转 确保是左对齐
fflush(stdout);
--***t;
sleep(1);
}
printf("\n");
}
int main() {
test();
return 0;
}
- 当前设置倒计时从
100开始 - 关于
printf中的参数%-3d\r的解释-
%d的作用:表示输出数字***t,用于显示倒计时 -
3的作用:用于控制输出显示位宽为3,倒计时的数字是几位,位宽就设置为几。 -
-的作用:设置位宽后,C程序默认为右对齐,我们想让数字在当前行的最左侧显示,要用-实现左对齐。 -
\r的作用:用于实现仅回车,回到当前行的开始,覆盖打印实现倒计时的效果。
-
- 使用
fflush(stdout)将缓冲区内的数据立即刷新出来 -
sleep(1)每隔一秒循环一次
错误演示
位宽不够带来的影响
- 位宽小于数字的位数时,会出现数字残余的情况。
- 由于显示器是字符设备,只会一个一个打印字符,123实际上是1 2 3三个字符连在一起表示的
- 以下是从10开始计数的错误例子
- 正确设置位宽即可解决。
设置位宽后不反转带来的影响
- 不用
-进行反转会导致数字不靠左显示- 对于倒计时来说影响甚微,但靠右显示的话,会导致进度条从右向左加载!
不使用\r回车带来的影响
- 不使用
\r会导致数字接连不断的出现,不符合倒计时的效果。
总结回顾倒计时
printf中的格式化控制参数缺一不可
- 关于
printf中的参数%-3d\r的理解-
%d表示输出数字***t,用于显示倒计时 -
3用于控制输出显示位宽为3,倒计时的数字是几位,位宽就设置为几。 - 设置位宽后,C程序默认为右对齐,我们想让数字在当前行的最左侧显示,要用
-实现左对齐。 -
\r用于实现仅回车,回到当前行的开始,覆盖打印实现倒计时的效果。
-
- 使用
fflush(stdout)将缓冲区内的数据立即刷新出来