在开始实现进度条之前首先要清楚三个概念:
回车概念( \r ),换行概念( \n ),行缓冲区概念
\r&&\n概念:
在不同的操作系统下回车换行的意义不同:
Windows:
- 回车 \r:回到 当前行的行首,而 不会换到下一行,如果接着输出的话,本行以前的内容会被逐一覆盖;
- 换行 \n:换到 当前位置的下一行,而 不会回到行首;
- 在Windows系统中,按回车键,等于输入<回车><换行>,即<\r><\n>;
Unix:
- 每行结尾只有“<换行>”,即"\n";
Mac OS:
- 每行结尾是“<回车>”,即"\r";
如果将Unix/Mac系统下的文件在Windows里打开,所有文字会变成一行;
如果将Windows里的文件在Unix/Mac下打开,在每行的结尾可能会多出一个^M符号;
行缓冲区概念:
缓冲区分为三种类型:全缓冲,行缓冲和不带缓冲;
- 全缓冲:
在这种情况下,当填满标准I/O缓存后才进行实际I/O操作。全缓冲的典型代表是对磁盘文件的读写。 - 行缓冲
在这种情况下,当在输入和输出中遇到换行符时,执行真正的I/O(流)操作。这时,我们输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O操作。典型代表是键盘输入数据。 - 不带缓冲
也就是不进行缓冲,标准出错情况stderr是典型代表,这使得出错信息可以直接尽快地显示出来。
理解了上面的概念,下面来实现进度条。
一,普通版进度条
在实现时用到了usleep()函数和fflush()函数。
usleep()函数的作用是:让程序睡眠,参数单位默认为秒,包含在”unistd.h”头文件中;
fflush()函数的作用是:清除读写缓冲区,参数为标准输入\输出流 ;
如果不使用fflush()函数,在进度条输出时,会看到每次刷新出来的内容是增加的,不是一个一个的出现。
#include<stdio.h>
#include<unistd.h>
int main ()
{
char bar[102] = {0};//用来显示进度条
int i = 0;
const char* laber = "|/-\\";//添加一个闪动的光标,用来表示进度条正在进行
// 这里的两个'\'是防止转义
while(i <= 100)
{
printf("[%d][%-100s][%c]\r",i,bar,laber[i%4]);//注意这里的回车 ”\r“
//这里100的意思是预留位置,100之前的 ‘-’是左对齐
fflush(stdout);
bar[i++] = '*';
usleep(50000);//让程序睡眠,
}
printf("\n");
return 0;
}
二,彩色版进度条
在普通版的进度条的基础上进行些许修改,让进度条的显示方式更加贴近实际所看到的进度条。
这里还需要了解一些系统显示方面的东西:
终端的字符颜色由转义序列控制,是文本模式下的系统显示功能,与具体语言无关。
转义序列以控制字符’ESC’开头。多数转义序列超过两个字符,故通常以’ESC’和左括号’[‘开头。该起始序列称为控制序列引导符,通常由’\033[‘或’\e[‘代替。
通过转义序列设置终端显示属性时,可采用以下格式:
\033[Param{;Param;...}m 或 \e[Param{;Param;...}m
其中,\033[或\e[为引导转义序列,Param为属性项,{ }表示可选,多个选项间用分号间隔,m表示设置属性并结束转义序列。
常见的属性项为(具体可根据:man console_codes命令查询):
显示序列:
\033[0m 关闭转义序列
\033[1m 粗体或高亮
\033[5m 闪烁
前景颜色序列:
\033[30m 黑
\033[31m 红
\033[32m 绿
\033[33m 黄
\033[34m 蓝
\033[35m 洋红
\033[36m 青
\033[37m 白
背景颜色序列:
与前景颜色对对应,前景色是30+,背景色是40+
下面我们就可以将进度条实现的更加贴近实际所看到的样式;
#include<stdio.h>
#include<unistd.h>
int main()
{
char bar[102] = {0};
size_t i = 0;
while(i <= 100)
{
printf("\033[41m\033[37m\033[1m [%-3d%%]%s\033[0m\r",i,bar);
fflush(stdout);
bar[i++] = ' ';
usleep(50000);
}
printf("\n");
return 0;
}
keep Running