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

c 复制代码
process:process.c main.c
	gcc -o $@ $^
.PHONY:clean
clean:
	rm -f $@

process.c

c 复制代码
#include "process.h"
#include<string.h>
#include<unistd.h>

#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");
}

process.h

c 复制代码
#pragma once 

#include<stdio.h>
void process();

main.c

c 复制代码
#include "process.h"

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

重点代码解读

进度条效果


(二)实际工程实践版本

下载逻辑

Makefile

c 复制代码
process:process.c main.c
	gcc -o $@ $^
.PHONY:clean
clean:
	rm -rf process

process.c

c 复制代码
#include "process.h"
#include<string.h>
#include<unistd.h>

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));
    }
}

process.h

c 复制代码
#pragma once 

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

#define SIZE 101
#define MAX_RATE 100
#define STYLE '#'
#define STIME 1000*40

void process_v2(int);

main.c

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;
}

重点代码解读


改进

process.h

c 复制代码
#pragma once 

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

#define SIZE 101
#define MAX_RATE 100
#define STYLE '#'
#define STIME 1000*40

typedef void(*callback_t)(int);
void process_v2(int);

main.c

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;
}

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

🎗️改进的版本:

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

总结

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

(三)简单的美化风格

Makefile

c 复制代码
process:process.c main.c
	gcc -o $@ $^
.PHONY:clean
clean:
	rm -rf process

process.c

c 复制代码
#include "process.h"
#include<string.h>
#include<unistd.h>

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;
        }
    }
}

process.h

c 复制代码
#pragma once 

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

#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);

main.c

c 复制代码
#pragma once 

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

#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);

进度条效果


模拟加载中效果

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

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

process.c
c 复制代码
#include "process.h"
#include<string.h>
#include<unistd.h>

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;
        }
    }
}
process.h
c 复制代码
#pragma once 

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

#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);
main.c
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;
}
Makefile
c 复制代码
process:process.c main.c
	gcc -o $@ $^
.PHONY:clean
clean:
	rm -rf process
重点代码解读


进度条效果

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

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



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

相关推荐
高山上有一只小老虎6 分钟前
翻之矩阵中的行
java·算法
火钳游侠20 分钟前
java单行注释,多行注释,文档注释
java·开发语言
曼巴UE523 分钟前
UE FString, FName ,FText 三者转换,再次学习,官方文档理解
服务器·前端·javascript
wanhengidc32 分钟前
云手机的存储空间可以灵活扩展吗?
运维·服务器·科技·智能手机·云计算
code bean43 分钟前
【CMake】为什么需要清理 CMake 缓存文件?深入理解 CMake 生成器切换机制
java·spring·缓存
selt7911 小时前
Redisson之RedissonLock源码完全解析
android·java·javascript
Danileaf_Guo1 小时前
256台H100服务器的RoCEv2无损与全互联算力网络建设方案
运维·服务器·网络
RestCloud1 小时前
智能制造的底层基建:iPaaS 如何统一 ERP、MES 与 WMS 的数据流
java·wms·erp·数据传输·ipaas·mes·集成平台
解压专家6661 小时前
怎么找书?怎么传输?在Kred里完成的全过程
运维·服务器·网络
guslegend1 小时前
SpringBoot源码剖析
java