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

文章目录

  • 一、前提引入
    • 🎗️下面的代码什么现象?
    • 🎗️下面的代码什么现象?
  • 二、缓冲区
  • 三、回车换行
    • 🎗️注意
    • 🎗️图解
    • 🎗️老式回车键造型(意思是充当两个动作)
    • 🎗️\r 和 \n
    • 🎗️倒计时代码
      • 代码1
      • 代码2
      • 思考
  • 四、进度条
    • 预想的进度条效果
    • 构想代码结构
    • (一)简单原理版本
      • Makefile
      • process.c
      • process.h
      • main.c
      • 重点代码解读
      • 进度条效果
    • (二)实际工程实践版本
      • 下载逻辑
      • Makefile
      • process.c
      • process.h
      • main.c
      • 重点代码解读
      • 改进
      • process.h
      • main.c
      • 总结
    • (三)简单的美化风格
      • Makefile
      • process.c
      • process.h
      • main.c
      • 进度条效果
      • 模拟加载中效果
        • process.c
        • process.h
        • main.c
        • Makefile
        • 重点代码解读
        • 进度条效果
      • C语言扩展--给进度条带上颜色

在这里插入图片描述

一、前提引入

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

在这里插入图片描述
🎗️现象:马上打印出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 $@

process.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

#pragma once 

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

main.c

#include "process.h"

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

重点代码解读

在这里插入图片描述

进度条效果

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

(二)实际工程实践版本

下载逻辑

在这里插入图片描述

Makefile

process:process.c main.c
	gcc -o $@ $^
.PHONY:clean
clean:
	rm -rf process

process.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

#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

#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

#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

#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

process:process.c main.c
	gcc -o $@ $^
.PHONY:clean
clean:
	rm -rf process

process.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

#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

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

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

进度条效果

在这里插入图片描述

在这里插入图片描述

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

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

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


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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/157818.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

洛谷 P3131 [USACO16JAN] Subsequences Summing to Sevens S

被普及-卡的没思路真是蒟蒻啊233 优化思路 每次都在枚举(a[r]-a[l-1])%70&#xff0c;所以可以认为数组大小对最终答案没有影响&#xff0c;考虑对前缀和数组取模&#xff0c;那么如果有a[r]的值等于a[l-1]的值相等&#xff08;即余数相等&#xff09;&#xff0c;那么两者相减…

C++实现KNN和K-Means

学校机器学习课程的实验课要求实现KNN和K-Means&#xff1a; &#xff08;平时没听课&#xff09;临时去查了一下KNN和K-Means是啥&#xff0c;然后自己用C写了小例子&#xff0c;想着写都写了那就把代码贴出来吧。 顺便再聊聊自己对于这俩算法的理解。 下面是文心一言的回答…

如何快速下载mysql的不同版本并启动mysql服务?

如何快速下载mysql的不同版本并启动mysql服务&#xff1f; 下载mysql的安装版本 首先我们要使用到迅雷去下载&#xff0c;因为迅雷下载是很快的。在迅雷里面搜索下面的Mysql Installer安装窗口&#xff0c;如下图&#xff1a; 连接&#xff1a;https://dev.mysql.com/downlo…

如何避免被他人“背刺”?

请公主们、王子们&#xff0c;花点时间看一下&#xff0c;谢谢。 在人与人相处中&#xff0c;难免不会碰上与人合作交往&#xff0c;虽然大多数时候我们是选择熟悉一点的朋友&#xff0c;但是也不能掉以轻心&#xff0c;现实生活中也不是不存在被亲戚朋友“背刺”&#xff0c;…

MySQL主从同步

文章目录 MySQL主从同步概述MySQL主从同步原理MySQL主从同步结构模式MySQL主从同步搭建搭建步骤一主一从实验环境master主机slave1主机验证主从同步 一主多从master主机slave2主机验证主从同步 链式复制&#xff08;主从从&#xff09;slave1主机slave2主机验证链式复制 MySQL主…

SpringBoot2—基础篇

目录 快速上手SpringBoot • SpringBoot入门程序开发 基于Idea创建SpringBoot工程&#xff08;一&#xff09; 基于官网创建SpringBoot工程&#xff08;二&#xff09; 基于阿里云创建SpringBoot工程&#xff08;三&#xff09; 手工创建Maven工程修改为SpringBoot工程&…

GPT-4V新玩法登顶GitHub热榜,随手一画就能生成网页!web开发者:感受到了威胁

西风 发自 凹非寺 量子位 | 公众号 QbitAI 随手一画就能生成网页&#xff01;GPT-4V新玩法登顶GitHub热榜&#xff0c;狂揽3000&#x1f31f;&#xff1a; 现在只要简单画一画&#xff0c;框一框&#xff0c;点击执行&#xff1a; “啪”地一下&#xff0c;一个带有各种“按钮…

Apriori算法

Apriori算法由R. Agrawal和R. Srikant于1994年在数据集中寻找布尔关联规则的频繁项集。该算法的名称是Apriori&#xff0c;因为它使用了频繁项集属性的先验知识。我们应用迭代方法或逐层搜索&#xff0c;其中k-频繁项集用于找到k1个项集。 为了提高频繁项集逐层生成的效率&…

oracle21c安装报错【[INS-32014] 指定的 Oracle 基目录位置XXX无效】

一.问题 [INS-32014] 指定的 Oracle 基目录位置XXX无效 二.解决办法 安装包的文件放置不可以在中文字文件夹下面&#xff0c;改为英文【soft】,就可以成功安装完成了&#xff01;

米尔AM62x核心板,高配价低,AM335x升级首选

AM335x是TI经典的工业MPU&#xff0c;它引领了一个时代&#xff0c;即工业市场从MCU向MPU演进&#xff0c;帮助产业界从Arm9迅速迁移至高性能Cortex-A8处理器。随着工业4.0的发展&#xff0c;HMI人机交互、工业工控、医疗等领域的应用面临迫切的升级需求&#xff0c;AM62x处理器…

mysql统计整个数据库记录条数

SELECTSUM(TABLE_ROWS) FROM(SELECTTABLE_NAME,TABLE_ROWSFROMINFORMATION_SCHEMA.TABLESWHERETABLE_SCHEMA 数据库名&#xff0c;其他不变) t;效果如下&#xff1a;

[pybind11] debug C++代码

首先要有一个项目&#xff0c;我发布在github上了【传送门】 项目的结构如下&#xff1a; 其中src目录下是C代码&#xff0c;test.py是python测试代码。 然后直接开始演示。 1、把项目下载到本地 git clone --recursive https://github.com/immortalmin/pybind11_debug_eg.g…

4月2日-3日·上海 | 3DCC 第二届3D细胞培养与类器官研发峰会携手CGT Asia 重磅来袭

类器官&#xff08;Organoids&#xff09;作为干细胞研究领域最重要的成果之一&#xff0c;在基础医学研究、转化医学及药物研发领域展现出巨大的应用潜力&#xff0c;特别是在精准医疗以及药物安全性和有效性评价等方向凭借其先天优势引起了极大的市场关注&#xff0c;成为各大…

采访仁川市政府:探索《仁川登陆行动》体验及其 NFT 作品集背后的故事!

请简单介绍一下自己 大家好&#xff0c;我是仁川市政府品牌经理崔俊浩&#xff0c;负责《仁川登陆行动》的元宇宙活动。很高兴见到您。 是什么启发了你创作《仁川登陆行动》体验&#xff1f; 《仁川登陆行动》并未得到广泛认可&#xff0c;并且被认为是一项几乎不可能完成的任务…

golang学习笔记——斐波纳契数列

斐波纳契数列 编写一个程序来计算某个数字的斐波纳契数列。 斐波那契数列是一个数字列表&#xff0c;其中每个数字是前两个斐波那契数字之和。 例如&#xff0c;数字 6 的序列是 1,1,2,3,5,8&#xff0c;数字 7 的序列是 1,1,2,3,5,8,13&#xff0c;数字 8 的序列是 1,1,2,3,5…

前端实现页面内容的截图与下载(html2canvas)

今天是一个发文的好日子&#x1f600;~ &#x1f447;&#x1f447;&#x1f447; 一个需求&#xff0c;要截取页面中的内容并截图保存&#xff0c;来看一看我是怎么实现的吧&#xff1a; 这里需要使用到插件--html2canvas 1.安装并引入html2canvas npm install html2canv…

创作者焦点:Temple of Dum-Dum(试炼 3)

《Bomkus 博士的试炼》创作的幕后花絮。 《创作者焦点》系列共分为六部分&#xff0c;重点介绍《Bomkus 博士的试炼》的游戏创作过程及其独特的游戏功能。 Temple of Dum-Dum&#xff1a; Temple of Dum-Dum 是 Bomkus 博士试炼中的第三个挑战&#xff0c;该试炼由六项体验组成…

阎良区公益创投之“小飞机大梦想” 航模DIY主题活动

创造是人类探索迈出的第一步&#xff0c;科学是开启奇妙世界的金钥匙。为进一步提升“未来星”对科技知识的兴趣&#xff0c;培养他们的科学创新精神&#xff0c;11月16日&#xff0c;阎良区社会组织公益创投——“未来星”助力乡村留守儿童成长计划项目在阎良区聚宝小学开展“…

【hive-解决】HiveAccessControlException Permission denied: CREATEFUNCTION

文章目录 一.任务描述二. 解决 一.任务描述 Error while compiling statement: FAILED: HiveAccessControlException Permission denied: Principal [nameroot, typeUSER] does not have following privileges for operation CREATEFUNCTION [ADMIN PRIVILEGE on INPUT, ADMIN…

springboot 数据传输的加密解密方式一: AES(对称加密)

全文目录,一步到位 1.加密/解密方式一: AES1.1 AES加密简介1.2 AES解密简介1.3 AES细致介绍(外链) 2. AES加密解密使用2.1 应用场景2.2 工具包使用方式2.2.0 (关键)生成一个秘钥(16位)2.2.1 AES加密文本2.2.2 AES解密文本2.2.3 AES加密文件(源)2.2.4 AES解密文件(源)2.2.5 文件…