LINUX 实现终端动态进度条记录

1、转义字符 \r \n 的区别

\r 代表回车,他会清空光标所在行设为数据并将该行的内容清除。

\n 代表换行,将光标移动到下一行。

2、ffush的作用

fflush刷新缓存,fflash(stdout),就是将标准输出的缓存输出并清空。

我们知道LINUX中stdout是行缓冲,啥意思,遇到换行符\n才输出缓存内容

3、动态进度条实现原理

通过一个buff 或者直接通过 printf 输出ESC 控制符设置 ,设置前景或者背景色,表示进度。

在开始输出前输出\r 将光标移动至行首并清空行。

输出完毕,调用 fflash(stdout) ,清空缓存,防止下次还输出上次的值。

3、实现

颜色控制头文件

c 复制代码
#ifndef __COLOR_H
#define __COLOR_H

//进度条使用背景色
#define COLOR_RED       "41"
#define COLOR_GREE      "42"
#define COLOR_YELLOW    "43"
#define COLOR_WHITE     "47"
//数字使用前景色
#define COLOR_RED_NUM       "31"   
#define COLOR_GREE_NUM      "32"
#define COLOR_YELLOW_NUM    "33"   
#define COLOR_WHITE_NUM     "37"   

#endif/*__COLOR_H*/

字符控制头文件

c 复制代码
#ifndef __SHOW_TYPES_H
#define __SHOW_TYPES_H




#endif/*__SHOW_TYPES_H*/

总控制头文件

c 复制代码
#ifndef __CONTROL_H
#define __CONTROL_H
//颜色头文件
#include "color.h"
#include "show_types.h"

//进度条宽度
#define BAR_WIDTH  50
#define ESC_PREFIXES    "\033["
#define ESC_SUFFIX      "m"
#define ESC_NULL        "\033[0m"
//==================================
//是否用字符表示进度条
#define USE_CHAR    1
#if USE_CHAR
//进度条 已完成部分字符
#define CONTROL_HEAD_CHAR "#"

//进度条未完成部分 字符
#define CONTROL_TAIL_CHAR " "
#endif /*#if USE_CHAR*/
//==================================

//进度条 已完成部分 颜色
#define CONTROL_HEAD_COLOR        COLOR_GREE
//进度条未完成部分 颜色
#define CONTROL_TAIL_COLOR        COLOR_WHITE


//==================================
//是否显示进度数字
#define PROGRESS__NUM     1

#if PROGRESS__NUM

#define PROGRESS__NUM_COLOR   COLOR_RED_NUM //color

#endif/*#if CONTROL_NUM*/
//==================================

源代码和测试函数

c 复制代码
#include <strings.h>
#include "control.h"
#include <unistd.h>
void show_bar(int progress,int total)
{
    char head_buff[64]={0}; //用来拼接控制字符串
    char tail_buff[64]={0}; //用来拼接控制字符串
    char num_buff[64]={0};
    int progress_num = (progress*100)/total; 
    bzero(head_buff,sizeof(head_buff));
    bzero(tail_buff,sizeof(head_buff));

    strncat(head_buff,ESC_PREFIXES,sizeof(ESC_PREFIXES));
    strncat(tail_buff,ESC_PREFIXES,sizeof(ESC_PREFIXES));
    strncat(head_buff,CONTROL_HEAD_COLOR,sizeof(CONTROL_HEAD_COLOR));
    strncat(tail_buff,CONTROL_TAIL_COLOR,sizeof(CONTROL_TAIL_COLOR));
    strncat(head_buff,ESC_SUFFIX,sizeof(ESC_SUFFIX));
    strncat(tail_buff,ESC_SUFFIX,sizeof(ESC_SUFFIX));
    #if USE_CHAR
    strncat(head_buff,CONTROL_HEAD_CHAR,sizeof(CONTROL_HEAD_CHAR));
    strncat(tail_buff,CONTROL_TAIL_CHAR,sizeof(CONTROL_TAIL_CHAR));
    #else
    strncat(head_buff," ",sizeof(" ")); 
    strncat(tail_buff," ",sizeof(" "));
    #endif
    strncat(head_buff,ESC_NULL,sizeof(ESC_NULL));
    strncat(tail_buff,ESC_NULL,sizeof(ESC_NULL));
    #if PROGRESS__NUM
    bzero(num_buff,sizeof(head_buff));
    strncat(num_buff,ESC_PREFIXES,sizeof(ESC_PREFIXES));
    strncat(num_buff,PROGRESS__NUM_COLOR,sizeof(PROGRESS__NUM_COLOR));
    strncat(num_buff,ESC_SUFFIX,sizeof(ESC_SUFFIX)); 
    #endif

    //start show
    int i;
    printf("\r[");
    for(i=0;i<BAR_WIDTH;i++)
    {
        if(i<(progress_num/(100/BAR_WIDTH)))
        {
            printf("%s",head_buff);
        }
        else
        {
            printf("%s",tail_buff);
        }
    }
    printf("]  ");
    #if PROGRESS__NUM
    printf("%s",num_buff);
    printf("%d %%",progress_num);
    printf("%s",ESC_NULL);
    #endif
    fflush(stdout);
}

int main()
{
    int i =0;
    for(i=1;i<=130;i++)
    {
        show_bar(i,130);
        usleep(5000);
    }
    printf("\n Download complete\n");
}

问题记录

1、终端作为一个进程,它的stdin\stdout\stderr缓存是怎样的?为什么终端中开启进程,进程的stdin\stdout\stderr 是直接在终端输出?这其中有什么关系?

相关推荐
捕鲸叉4 分钟前
怎样在Linux PC上调试另一台PC的内核驱动程序,以及另一台Arm/Linux上的程序和驱动程序
linux·arm开发·软件调试·诊断调试
孤寂大仙v4 分钟前
【Linux】进程状态
linux·运维·服务器
原谅我很悲7 分钟前
在VMwareFusion中使用Ubuntu
linux·运维·ubuntu
Linux运维技术栈30 分钟前
消息队列实战指南:三大MQ 与 Kafka 适用场景全解析
运维·分布式·kafka·消息队列·mq
Zfox_1 小时前
【Linux】应用层自定义协议与序列化
linux·服务器·c语言·c++
杰克崔1 小时前
通过内核模块按fd强制tcp的quickack方法
linux·运维·服务器·网络·tcp/ip
m0_748239631 小时前
SQL2000在win10上安装的方法
运维·服务器
程序设计实验室2 小时前
SSH 跳板机原理与配置:实现无缝跳板连接,一步直达目标主机
linux
阿^觅2 小时前
基础IO -- 动静态库(1)
linux·服务器
Channing Lewis2 小时前
Python 3.9及以上版本支持的新的字符串函数 str.removeprefix()
服务器·python