make/Makefile的使用和进度条小程序

1. make/Makefile的使用

makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作;makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。

make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建,make会根据makefile的内容,完成编译/清理工作。

2. make/Makefile原理

使用make mytest或者make可以执行gcc test.c -o mytest

使用make clean可以执行rm -f mytest

make和makefile

makefile默认对最新的可执行程序不重新生成

原理

依赖关系和依赖方法是成对出现的;其中,.PHONYY:XXX中的XXX对应的方法总是要执行的,即只要运行make clean就可以执行clean的命令。

补充知识1:为什么makefile对最新的可执行程序,默认不重新形成?

对于大型软件,如果全部重新编译,会耗费很多资源,只对改变的文件进行编译可以提高编译效率

补充知识2:makefile是怎么知道程序需要被编译的?

通过对比可执行文件的最近修改时间和源文件最近的修改时间

3. make/makefile的相关知识

1)make/makefile会自动根据文件中的依赖关系进行自动推导,帮助我们执行所有的相关方法,需要注意的是,**最后执行的依赖列表和依赖方法要放到第一位,**如图中第一二行,其他的顺序可以随便放。如果中间过程某个文件无法形成,则会推导失败

执行顺序

2) 相 当于依赖关系名称, ^相当于依赖关系名称, 当于依赖关系名称,@相当于目标文件名称

替换

3)可以定义变量,相当于C语言的宏。第一行中左侧是变量名,右侧是变量内容,等号两边不能带空格;使用变量的方法是$(XXX),XXX就是变量名。如果不想显示命令,可以在前面带个@,这样就不会出现命令了

定义变量

4. 进度条小程序

在写进度条之前,需要先掌握回车换行概念、缓冲区认识以及模拟倒计时上手。

4.1 回车和换行

回车和换行是两个操作,回车是将光标返回到当前行开头换行就是光标移动到下一行。C语言中 \n 是 回车+换行, \r 则是回车;如果 \r\n 一起使用,则 \n 只执行换行。

回车换行

4.2 缓冲区

缓冲区是计算机内存中的一块临时存储区域,用于在数据从一个地方传输到另一个地方时暂存数据。

首先需要明确的是:下面的C程序执行顺序一定是执行第六行再执行第七行,因为程序都是从上都下执行的。

那当系统执行sleep时,printf的字符串为什么没有直接显示出来?它又存到哪里了呢?答案就是缓冲区。简单来说:程序结束时一般会自动冲刷缓冲区,所以在sleep结束之后,缓冲区的内容就会显示在屏幕上,就可以看到字符串了。

那如果不想等待sleep结束,那要怎样办?

1)\n。这个是设计和兼容效率、阅读习惯的原因,因为一次刷新字会过多,一个个刷新不符合阅读习惯

2)缓冲区满了。这时就会释放缓冲区,也会执行刷新

3)强制刷新。调用 fflush() 可以强制进行刷新

刷新

执行程序

4.3 倒计时

原理是执行回车但不执行换行,同时强制刷新缓冲区,并进行sleep,这样光标会处于第一行,数字也会显示出来。

如果倒计时数字是2位或者以上,需要在打印时用%nd,n为位数,这样才能对全部字符(显示器显示的100是显示3个字符,而不是1个数字)进行覆盖

倒计时

倒计时效果

4.4 进度条

在掌握上面的知识后,就可以写一个简单的进度条加载小程序。它是利用了缓冲区强制刷新以及只回车不换行的原理,和倒计时有相似的模样。

1)简单进度条

这里将程序分成4个,makefile负责执行编译程序,Processbar.h包含头文件以及函数接口,Processbar.c则是实现进度条,Main.c相当于启动器。更多说明部分可以参照程序中的注释。

Processbar.h

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

#define Length 101  //定义进度条长度
#define Style '#'   //定义进度条样式
 
void ProBar();

Processbar.c

#include "Processbar.h"

void ProBar()
{
    char bar[Length];
    char* lable = "|/-\\";           //最右侧样式
    memset(bar, '\0', sizeof(bar));  //初始化数组
    int len = strlen(lable);
    int cnt = 0;
    while(cnt <= 100)
    {
        printf("[%-100s], [%3d%%], [%c]\r", bar, cnt, lable[cnt%len]);		//打印进度条,进度百分比,最右侧动态变化
        fflush(stdout);  //强制刷新缓冲区
        bar[cnt++] = Style;
        usleep(2000);   //休眠,以微秒为单位
   }

    printf("\n");
}

Main.c

#include "Processbar.h"
 
int main()                                            {
	ProBar();

    return 0;
}

makefile

#文件已经包含了头文件,而且编译过程中会进行头文件展开
#因此可以不用包含头文件,写上也没有问题
Processbar:Main.c Processbar.c
	gcc Main.c -o $@ $^
.PHONY:clean
clean:
    rm -f $@ 

效果:

简单进度条

2)模拟下载场景

接下来模拟下载的场景,主要修改以下三个文件,makefile不变

Processbar.h

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

#define Length 101  //定义进度条长度
#define Style '#'   //定义进度条样式

void download();
void ProBar(double filesize, double current); //传入文件大小和下载进度
typedef void(*callback_t)(double, double); //回调函数

Processbar.c

这里说明两种方法,第一种是正常的调用,第二种采用回调函数

#include "Processbar.h"

void ProBar()
{
    char bar[Length];
    char* lable = "|/-\\";           //最右侧样式
    memset(bar, '\0', sizeof(bar));  //初始化数组
    int len = strlen(lable);
    double rate = current*100.0/filesize;
    int cnt = 0;
    int loop_count = (int)rate;
    while(cnt <= loop_count)
    {
        bar[cnt++] = Style;  //采用字符串拼接的方式,同时防止进度条闪烁
    }
    printf("[%-100s], [%3.1lf%%], [%c]\r", bar, rate, lable[cnt%len]);		//打印进度条,进度百分比,最右侧动态变化
	fflush(stdout);  //强制刷新缓冲区
}

void download(callback_t cb)
{
    double filesize = 100*1024*1024*1.0;  //模拟文件大小
    double current = 0.0;  //模拟当前下载大小
    double bandwidth = 1024*1024*1.0;  //模拟下载带宽                                                             
    printf("download begin, current: %lf\n", current);
    while(current <= filesize)
    {
        //1、正常的调用方法,传入文件大小和当前下载大小
        //ProBar(filesize, current);
        //2、用回调函数传入
        cb(filesize, current);
        current += bandwidth;  //模拟下载贷款
        usleep(20000);
    }
    
    printf("\ndownload done, filesize: %lf\n", filesize);
}

Main.c

#include "Processbar.h"
 
int main()                                            {
    //1、模拟下载
	//download();
    //2.用回调函数传入
    download(ProBar);

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值