• Linux---(七)Makefile写进度条(三个版本)



    在这里插入图片描述

    一、前提引入

    🎗️下面的代码什么现象?

    在这里插入图片描述
    🎗️现象:马上打印出Hello Makefile!
    在这里插入图片描述

    🎗️下面的代码什么现象?

    在这里插入图片描述
    🎗️现象:停留三秒后打印出Hello Makefile!
    在这里插入图片描述

    现象是先sleep!但是一定是printf先执行,printf早就执行了,只不过字符串没有被显示出来罢了。所以在sleep期间,字符串在哪里?
    答案:在输出缓冲区。

    二、缓冲区

    🎗️C/C++语言,会针对标准输出,给我们提供默认的缓冲区。
    🎗️输出缓冲区在哪里呢?

    在标准输出流。C/C++默认会打开三个文件流:标准输入流、标准输出流、标准错误流。

    🎗️fflush(stdout) 刷新缓冲区
    🎗️\n 是一种刷新的策略 行刷新

    C程序是默认有输出缓冲区的,数据输出时会默认放在输出缓冲区。之所以可以立马见到数据,是因为该数据被刷新了;如果没有立马见到它,该数据没有被刷新,被暂存在输出缓冲区stdout当中。强制刷新fflsh(stdout)可使数据立马显示出来。

    三、回车换行

    🎗️注意

    回车换行是两个动作
    回车是让光标回到该行的最开始位置
    换行是换到下一行

    🎗️图解

    在这里插入图片描述

    🎗️老式回车键造型(意思是充当两个动作)

    在这里插入图片描述

    🎗️\r 和 \n

    🎗️在C语言中,\r代表回车,\n代表换行
    🎗️在Linux中,\r代表回车,\n代表回车和换行

    🎗️倒计时代码

    代码1

    在这里插入图片描述
    效果
    形成一个9到1的倒计时效果(打印完一个数字,回车回到最开始打印,下一个数字覆盖上一个数字的打印结果)
    注意:如果没有刷新缓冲区那句代码,那么什么也不会显示出来。

    代码2

    在这里插入图片描述
    🎗️效果
    形成一个从100的倒计时
    🎗️注意点
    控制两位字符的输出宽度,可达到10的倒计时效果;控制三位字符的输出宽度,可达到100的倒计时效果。控制几位字符就在%d的d前面加数字。
    输出结果如果不设置对齐方式,可能会出现覆盖从而达不到预想效果。输出结果左对齐,在%后加上-

    思考

    🎗️我们向显示器打印的数字真的是数字吗?

    答案:不是
    往显示器输出123,实际上输出的是1字符,2字符,3字符。
    显示器只能显示字符。
    因此显示器叫做显示器字符设备。

    🎗️我们从键盘上读取到的内容,是什么呢?

    b比如说我们从键盘输入1234,键盘读取到的并不是一千两百三十四,而是1字符、2字符、3字符、4字符,然后由scanf将字符串转成整数,放到对应的变量里,这样才有了整数。

    四、进度条

    预想的进度条效果

    在这里插入图片描述

    构想代码结构

    在这里插入图片描述

    (一)简单原理版本

    Makefile

    process:process.c main.c
    	gcc -o $@ $^
    .PHONY:clean
    clean:
    	rm -f $@
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    process.c

    #include "process.h"
    #include
    #include
    
    #define SIZE 101
    #define MAX_RATE 100
    #define STYLE '#'
    #define STIME 1000*40
    
    const char *str="|/-\\";
    
    void process(){
        int rate=0;
        char bar[SIZE];
        memset(bar,'\0',sizeof(bar));
        int num=strlen(str);
    
        while(rate<=MAX_RATE){
            printf("[%-100s][%d%%][%c]\r",bar,rate,str[rate%num]);
            fflush(stdout);
            usleep(STIME);  
            bar[rate++]=STYLE;
        }
        printf("\n");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    process.h

    #pragma once 
    
    #include
    void process();
    
    • 1
    • 2
    • 3
    • 4

    main.c

    #include "process.h"
    
    int main(){
        process();
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    重点代码解读

    在这里插入图片描述

    进度条效果

    在这里插入图片描述
    在这里插入图片描述

    (二)实际工程实践版本

    下载逻辑

    在这里插入图片描述

    Makefile

    process:process.c main.c
    	gcc -o $@ $^
    .PHONY:clean
    clean:
    	rm -rf process
    
    • 1
    • 2
    • 3
    • 4
    • 5

    process.c

    #include "process.h"
    #include
    #include
    
    const char *str="|/-\\";
    
    void process_v2(int rate){
        static char bar[SIZE]={0};
        int num=strlen(str);
        if(rate<=MAX_RATE&&rate>=0){
            printf("[%-100s][%d%%][%c]\r",bar,rate,str[rate%num]);
            fflush(stdout);
            bar[rate]=STYLE;
        }
        if(rate==MAX_RATE){
            memset(bar,'\0',sizeof(bar));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    process.h

    #pragma once 
    
    #include
    #include
    #include
    
    #define SIZE 101
    #define MAX_RATE 100
    #define STYLE '#'
    #define STIME 1000*40
    
    void process_v2(int);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    main.c

    #include "process.h"
    
    #define TARGET_SIZE 1024*1024
    #define DSIZE 1024*10
    
    void download(){
        int target=TARGET_SIZE;
        int total=0;
    
        while(total<target){
            usleep(STIME);
            total+=DSIZE;
            process_v2(total*100/target);
        }
        printf("\n");
    }
    
    //下载的软件
    int main(){
        download();
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    重点代码解读

    在这里插入图片描述
    在这里插入图片描述

    改进

    process.h

    #pragma once 
    
    #include
    #include
    #include
    
    #define SIZE 101
    #define MAX_RATE 100
    #define STYLE '#'
    #define STIME 1000*40
    
    typedef void(*callback_t)(int);
    void process_v2(int);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述

    main.c

    #include "process.h"
    
    #define TARGET_SIZE 1024*1024
    #define DSIZE 1024*10
    
    void download(callback_t cb){
        int target=TARGET_SIZE;
        int total=0;
    
        while(total<target){
            usleep(STIME);
            total+=DSIZE;
            int rate=total*100/target;
            cb(rate);
        }
        printf("\n");
    }
    
    //下载的软件
    int main(){
        download(process_v2);
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在这里插入图片描述

    🎗️回调:把一段可执行的代码像参数传递给其他代码,而这段代码会在某个时刻被调用执行,这就叫做回调。
    🎗️改进的版本:

    这里,将更新显示的进度条的函数process_v2作为参数传递给download函数,在download函数中需要它时就调用它,调用以函数指针的形式来实现回调函数。

    总结

    版本2进度条不是在进度条函数内部进行循环打印的,这样有点不好,所以我们采用回调的方式,来进行某种任务的通知,动态更新进度条!(在下载任务中调用进度条)

    (三)简单的美化风格

    Makefile

    process:process.c main.c
    	gcc -o $@ $^
    .PHONY:clean
    clean:
    	rm -rf process
    
    • 1
    • 2
    • 3
    • 4
    • 5

    process.c

    #include "process.h"
    #include
    #include
    
    const char *str="|/-\\";
    
    void process_v3(double rate){
        static char bar[SIZE]={0};
        int num=strlen(str);
        if(rate<=MAX_RATE&&rate>=0){
            printf("[%-100s][%.1f%%][%c]\r",bar,rate,str[(int)rate%num]);
            fflush(stdout);
            if(rate<MAX_RATE){
                bar[(int)rate]=STYLE_BODY;
                bar[(int)rate+1]=STYLE_HEAD;
            }else{
                bar[(int)rate]=STYLE_BODY;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述

    process.h

    #pragma once 
    
    #include
    #include
    #include
    
    #define SIZE 101
    #define MAX_RATE 100
    #define STYLE '#'
    #define STIME 1000*40
    #define STYLE_BODY '='
    #define STYLE_HEAD '>'
    
    typedef void(*callback_t)(double);
    void process_v3(double);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    main.c

    #pragma once 
    
    #include
    #include
    #include
    
    #define SIZE 101
    #define MAX_RATE 100
    #define STYLE '#'
    #define STIME 1000*40
    #define STYLE_BODY '='
    #define STYLE_HEAD '>'
    
    typedef void(*callback_t)(double);
    void process_v3(double);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    进度条效果

    在这里插入图片描述
    在这里插入图片描述

    模拟加载中效果

    版本3基础上,模拟实现进度条加载过程中不移动时,数字不改变时,(即现实中加载的资源不足以1%时),后面的光标一直旋转(显示加载中)的效果。

    🎗️在process.c和main.c文件中做了修改

    process.c
    #include "process.h"
    #include
    #include
    
    const char *str="|/-\\";
    
    void process_v3(double rate){
        static char bar[SIZE]={0};
        int num=strlen(str);
        static int cnt=0;
    
        if(rate<=MAX_RATE&&rate>=0){
            cnt++;
            cnt=(cnt>=num?0:cnt);
            printf("[%-100s][%.1f%%][%c]\r",bar,rate,str[cnt]);
            fflush(stdout);
            if(rate<MAX_RATE){
                bar[(int)rate]=STYLE_BODY;
                bar[(int)rate+1]=STYLE_HEAD;
            }else{
                bar[(int)rate]=STYLE_BODY;
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    process.h
    #pragma once 
    
    #include
    #include
    #include
    
    #define SIZE 101
    #define MAX_RATE 100
    #define STYLE '#'
    #define STIME 1000*40
    #define STYLE_BODY '='
    #define STYLE_HEAD '>'
    
    typedef void(*callback_t)(double);
    void process_v3(double);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    main.c
    #include "process.h"
    
    #define TARGET_SIZE 1024*1024
    #define DSIZE 1024*10
    
    void download(callback_t cb){
        int testcnt=100;
        int target=TARGET_SIZE;
        int total=0;
    
        while(total<target){
            usleep(STIME);
            total+=DSIZE;
            double rate=total*100/target;
            if(rate>50.0&&testcnt){
                total=target/2;
                testcnt--;    
             }
        cb(rate);
        }
        cb(MAX_RATE);
        printf("\n");
    }
    
    //下载的软件
    int main(){
        download(process_v3);
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    Makefile
    process:process.c main.c
    	gcc -o $@ $^
    .PHONY:clean
    clean:
    	rm -rf process
    
    • 1
    • 2
    • 3
    • 4
    • 5
    重点代码解读

    在这里插入图片描述
    在这里插入图片描述

    进度条效果

    在这里插入图片描述

    在这里插入图片描述

    C语言扩展–给进度条带上颜色

    C语言有具体的语法可以设置不同的颜色,具体内容大家可以自行搜索,为进度条设置自己喜爱的颜色。

    在这里插入图片描述
    在这里插入图片描述


    本篇内容的学习就到这里啦!如果对友友们有帮助的话,可以关注后续的创作内容哦~👻

  • 相关阅读:
    设计模式-21状态模式(状态设计模式)详解
    分页查询的SQL优化
    【前端】判断是否为对象
    Java开发实习面试总结(49分钟)
    Intel确认酷睿第14代是最后一代酷睿i系列, 以后是酷睿Ultra的时代
    win部署CRM
    SQL必需掌握的100个重要知识点:使用子查询
    ssm冬奥会志愿者报名系统毕业设计源码241154
    MySQL 中数据表 id 值 连续 且 自动增长
    全新Storm Core API管理系统源码 免授权版
  • 原文地址:https://blog.csdn.net/qq_66238381/article/details/134348676