Linux实践 - 实现一个进度条吧

在这里插入图片描述

前言

进度条在我们日常生活中非常常见,比如下载文件、加载游戏时会有一个进度条方便我们确认当前的进度。在Linux中我们使用yum下载软件时也会出现进度条显示文件当前的下载进度,本文将会实现在Linux命令行中的进度条显示。
image.png


进度条

呈现效果

在开始实现具体代码之前,先来看看最终呈现的效果:
进度条演示.gif

前置知识 - 回车换行

在以往写代码中(C语言的printf),我们经常使用换行符\n以使本行打印完毕后使光标换到下一行的开始(最左边)。

示例

例子1:
image.png
换行符\n直接把缓冲区的hello world刷新到显示器上,之后程序休眠2秒结束。并且\n使光标换到下一行并回到最开始的位置,所以命令提示符也会出现在下一行的开始位置。
演示2.gif
例子2:
image.png
结尾没有\n,缓冲区的hello world在第5行代码执行完后显示器不显示,之后程序休眠2秒,程序结束时把缓冲区的内容hello world显示到显示器上,并且光标在其之后,而不是在下一行开始,现象就是命令提示符直接在hello world之后显示。
演示1.gif

image.png
第6行的fflush函数把缓冲区的内容(hello world)刷新到了显示器上,光标位置仍然在hello world的下一个位置
演示3.gif

换行符\n

**换行符,顾名思义就是把光标换到下一行,同时刷新行缓冲区,把行缓冲区的内容打印到显示器上。**这本来并不会把光标回到这一行的开始(这是回车\r)的功能,但是,编译器对换行符\n做了特殊处理,当只出现\n时会同时完成回车与换行的功能,使光标换到下一行并回到最开始的位置。

回车符\r

**回车符,把光标回退到本行的最开始位置。**回车符\r不会刷新缓冲区,所以缓冲区的内容不会被刷新到显示器上,导致的结果就是待打印的内容仍在缓冲区中,显示器上没有内容(不了解这一特性时,会怀疑程序是不是出问题了,其实并不是)。
要想正常显示缓冲区的内容,只需再加一句刷新缓冲区的代码(fflush)即可。

思路讲解

实现进度条增长,现象是进度条越来越长直到进度条达到最长时停止。
用字符数组来实现,进度为0%时进度条为0,进度为1%时进度条为1个字符…进度为100%时进度条为100个字符。

#define NUM 101// 进度条长度
char bar[NUM];
memset(bar, '\0', sizeof(bar));//初始化字符数组bar所有元素为'\0'

循环输出字符数组,每次输出字符数组之后,光标都要回到本行的最开始\r,然后字符数组内容+1;
单独使用\r待打印的内容会储存在缓冲区中,不会显示在屏幕上,所以需要使用fflush函数刷新缓冲区。

printf("[%-100s][%3d%%]\r", bar, cnt);
fflush(stdout);

演示4.gif
旋转光标的实现:在进度条加载中,其后经常会有一个持续旋转的圆圈,我采用"|/-\\"四个字符依次循环出现模拟旋转的光标。

char spin[5] = "|/-\\";
printf("%c", spin[cnt % 4];);

演示5.gif
进度条总进度为[0%, 100%],本例使用长度为101字符数组表示进度条主体,为了不使循环直接结束,每次循环都使程序休眠usleep(10^(-6)s)一定时间,也方面我们控制进度条执行的时间。

#define FIXEDTIME 5 //单位s
#define SPEED 1
usleep(FIXEDTIME / SPEED * 10000);

printf的颜色控制:
格式为:\033[属性1;属性2…;m
以**\033开头,[m中间是各种属性(某个数字表示),属性之间以;**分隔。

  1. 格式控制:

0 重置所有属性
1 高亮/加粗
5 闪烁

  1. 字体颜色:

30 黑色
31 红色
32 绿色
33 黄色
34 蓝色
35 品红
36 青色
37 白色

  1. 背景颜色:

40 黑色
41 红色
42 绿色
43 黄色
44 蓝色
45 品红
46 青色
47 白色

image.png

代码实现

头文件progressBar.h

#pragma once
#include <stdio.h>
#include <unistd.h>
#include <string.h>

#define NUM 101 //进度条长度
#define FIXEDTIME 5 // 5s
#define SPEED 2 //固定时间/SPEED                                                                                                  
extern void progressBar();

源文件main.c

#include "progress.h"

int main(){
    progressBar();
                                                                                                                                  
    return 0;
 }

源文件progressBar.c

#include "progress.h"
void progressBar(){
    char bar[NUM];
    char spin[5] = "|/-\\";
    const char* style = "*-+=#";
    memset(bar, '\0', sizeof(bar));

    int cnt = 0;
    while(cnt <= 100){
        printf("\033[47;31m[%-100s][%3d%%][%c]\r\033[0m", bar, cnt, spin[cnt % 4]);
        fflush(stdout);
        usleep(FIXEDTIME / SPEED * 10000);// 睡眠
        //sleep(1);
        bar[cnt++] = style[N];
     }
     printf("\n");
}

结语


T h e E n d TheEnd TheEnd

  • 30
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

re怠惰的未禾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值