Linux下的彩色渐变进度条_动图

彩色进度条

完成这个小程序需要一些预备知识

  • Linux下的色彩是如何编码的?
  • 进度条以什么样的形式展现?如何让printf?
  • 理解计算机缓冲区的概念。

##问题一

​ 在Linux下编程不能用到<windows.h>的头文件,那怎么实现彩色,我们需要研究一下Linux彩色打印。

​ Linux终端会解析一些,并且依据控制码来设置终端的绘制属性,所以只要输出流中包含ANSI控制码

就可以工作。

echo -e "\033[31m 字体\33[0m"		//红色的ANSI控制码是\033[31m

\033[31m 处开始使用红色作为字体的前景色,后面的绘制都使用红色,直到遇到属性关闭控制码,所以后面使用\033[0m 来关闭属性。

多个控制码一起使用,可以看到叠加效果,控制码之间顺序无所谓,不管叠加多少个,其关闭控制码仍然是\033[0m

控制码如下:

这里顺便用红色标记出我们编写progress bar 所需要的控制码

ANSI属性控制 功能
\033[0m 关闭所有属性
\033[1m 设置高亮度
\033[4m 下划线
\033[5m 闪烁
\033[7m 反显
\033[8m 消隐
\033[30m – \033[37m 设置前景色
\033[40m – \033[47m 设置背景色
\033[nA 光标上移n行
\033[nB 光标下移n行
\033[nC 光标右移n列
\033[nD 光标左移n列
\033[y;H 设置光标位置
\033[2J 清屏
\033[K 清除从光标到行尾的内容
\033[s 保存光标位置
\033[u 恢复光标位置
\033[?25l 隐藏光标
\033[?25h 显示光标
  • 文字背景色彩数字:(颜色范围:40-49)

    • 40:黑色
    • 41: 深红色
    • 42: 绿色
    • 43: 黄色
    • 44: 蓝色
    • 45: 紫色
    • 46: 深绿色
    • 47: 白色
  • 文字前景色数字:(颜色范围:30 - 39)

    • 30: 黑色
    • 31: 红色
    • 32: 绿色
    • 33: 黄色
    • 34: 蓝色
    • 35: 紫色
    • 36: 深绿色
    • 37: 白色

问题二

​ 一般进度条要给人视觉上的停留且应该连续进行打印,我们需要printf若干个符号#,sleep函数让进度条给人停留感。

​ 还有关于换行符\n和回车符\r的区别;

符号 ASCII码 意义
‘\r’ 10 回车,使光标到行首(carriage return)
‘\n’ 13 换行,使光标下移一格(line feed)

​ 在不同的操作系统这几个字符表现不同,比如在WIN系统下,这两个字符就是表现的本义,在UNIX类系统,换行\n就表现为光标下一行并回到行首,在MAC上,\r就表现为回到本行开头并往下一行,至于ENTER键的定义是与操作系统有关的。通常用的Enter是两个加起来。

而在打印应该使用回车,不能用换行,因为进度条只能是一行,不能跳到下一行去,从打印一个#开始,回车,光标回到这一行的行首,每次多打印一个#,将覆盖到前一次打印的光标,而且每次多一次。

  • 关于sleep函数和 usleep 函数

    头文件是<unistd.h>,定义函数:

    • unsigned int sleep(unsigned int seconds);
    • sleep 函数会令目前的进程暂停,直到到达参数seconds所指定的秒数,或是被信号中断。
    • void usleep(unsigned long usec);
    • usleep 函数参数单位是微秒

问题三_缓冲区

​ 计算机为了提高CPU的效率,同时减少程序的等待时间,还有一个原因,CPU并不直接操作硬件设备,驱动程序才直接操作硬件,而进行交互动作时,中间总要经过复杂的步骤,所以缓冲区,作为内存的一部分,存在是很有必要的。

​ 缓冲区分为全缓冲、行缓冲、不带缓冲。

​ 编写进度条的程序,我们用到行缓冲,Linux下的printf函数是带有行缓冲的,只有遇见换行符才会刷新缓冲区,而前面我们提到,进度条是不能用换行符的,只能用回车,所以就需要我们手动刷新缓冲区fflush(stdot)函数可以帮我们完成。

​ 关于缓冲区的介绍,这篇博文里有介绍缓冲区.

#include<stdio.h>                                               #include<unistd.h>
#include<string.h>
int main(void){
	char array[101];
	memset(array, 0, sizeof(array));
	int i = 0;
    int color;
 	const char* lable = "|/-\\";
	for(; i <= 100; i++){
 		color = i % 6;
 		color++;
   		array[i] = ' ';
      	switch(color){
           	case 1:     				printf("\033[25l\033[41m%s\x0d\033[1m\033[37m%d%%\33[0m", array, i);
           		break;
          	case 2:
                printf("\033[?25l\033[45m%s\x0d\033[1m\033[37m%d%%\33[0m", array, i);
                break;
           case 3:
                 printf("\033[?25l\033[44m%s\x0d\033[1m\033[37m%d%%\33[0m", array, i);
               break;
          case 4:
               printf("\033[?25l\033[42m%s\x0d\033[1m\033[37m%d%%\33[0m", array, i);
                break;
            case 5:
              printf("\033[?25l\033[46m%s\x0d\033[1m\033[37m%d%%\33[0m", array, i);
                break;
            case 6:
                printf("\033[?25l\033[40m%s\x0d\033[1m\033[37m%d%%\33[0m", array, i);
				break;
        }
		fflush(stdout);
 		usleep(100000);
 	}
 	printf("\n");
  	return 0;
}                                 

gif帧数小,实际进图条的渐变比较连续

  • gif帧数小,实际进图条的渐变比较连续
  • 如果你的电脑回车符达不到想要的效果,请换成回车符的ASCII码值。
  • 数组一定要初始化,不然你不知道,数组里面是否会遇到一个换行符,以外的刷新缓冲区。
  • 巧用取模运算。
  • 另外,如果你的界面放不下100个字符,需要将界面的字体调小:View->Zoom Out
    需要改进的地方:
    是否能用宏替换代替复杂的控制码,以及优化程序中重复语句。

猜你喜欢

转载自blog.csdn.net/weixin_41249411/article/details/83513026