个人主页:chian-ocean
文章专栏
前言
make
和Makefile
是编译和构建软件项目时非常常用的工具和文件,它们通常配合使用来自动化项目的编译过程。
make
定义:make
是一个构建自动化工具,用于根据项目文件的依赖关系自动完成编译、链接和构建过程。
make
主要用途:
- 编译源代码:自动从源代码生成可执行文件。
- 管理项目依赖:只重新编译那些发生变化的文件,确保编译过程更高效。
- 简化构建任务:把繁琐的编译命令写入
Makefile
,并通过简单的make
命令执行它们
make
的工作方式
Makefile
文件:make
的核心工作是读取一个叫Makefile
的文件,该文件定义了目标(要生成的文件)、它们的依赖关系以及生成它们的命令。- 依赖管理:
- 每个目标文件都有一组依赖和一个生成它的命令。
make
会比较源文件和目标文件的修改时间,如果源文件比目标文件更新,make
就会重新生成目标文件。
- 增量编译:通过判断哪些文件已修改,
make
只重新编译必要的部分。这种特性对于大型项目非常有用,因为它能极大地节省编译时间。
Makefile
定义:Makefile
是一个文本文件,描述了如何构建项目文件的规则、文件之间的依赖关系,以及执行的具体构建命令。
makefile
主要用途:
- 描述整个构建过程,使得
make
工具能够理解如何编译和链接项目。 - 让开发人员能够清晰地看到项目的依赖关系和构建步骤,并且可以在团队中共享。
makefile
基本组成:
- 目标(Target):通常是要生成的文件,例如对象文件或可执行文件。
- 依赖(Dependencies):目标文件所依赖的其他文件,如源文件和头文件。
- 命令(Commands):生成目标文件所需执行的命令。
target: dependenciescommand
注意:在命令行前面必须是 TAB 键,这在 Makefile
中是语法上的硬性要求,不能用空格代替。
makefile
示例
code:code.o g++ -o code code.o
code.o:code.sg++ -c code.s -o code.o
code.s:code.ig++ -S code.i -o code.s
code.i:code.cpp g++ -E code.cpp -o code.i
clean:rm -rf code code.i code.o code.s
当前目录:
执行:
make
make
和 Makefile
的优点
- 提高效率:手动编译多个源文件不仅繁琐,而且容易出错。
make
能将这些编译过程自动化,只需简单地运行make
即可完成所有工作。 - 管理复杂的依赖关系:对于大型项目,源代码之间的依赖关系错综复杂,
make
可以通过Makefile
自动处理这些依赖关系,确保每次构建只重新编译必需的部分。 - 团队合作和跨平台:通过编写一个清晰的
Makefile
,开发者可以确保构建过程在不同的系统上是一致的,不同的开发人员都可以轻松构建相同的项目。
进度条小程序
void progressBar()
{char s[5] = "|/-\\"; // 旋转动画符号的数组char bar[NUM]; // 用于存储进度条符号的数组memset(bar, '\0', sizeof(bar)); // 将 bar 数组初始化为空字符int cnt = 0; // 进度计数int len = sizeof(s); // 符号数组 s 的长度while (cnt <= 100) // 循环直到进度达到 100{// 打印进度条printf("[%-100s][%d%%][%c]\r", bar, cnt, s[cnt % len]);![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/dec237a1d49b491aa017974af7d009b3.png)fflush(stdout); // 强制刷新输出缓冲区,确保进度条即时显示bar[cnt++] = STYLE; // 在进度条的当前位置填入一个符号usleep(100000); // 休眠 100 毫秒}printf("\n"); // 输出换行符,表示进度条结束
}
你提供的代码是一段用 C 语言编写的实现控制台进度条的函数。这段代码使用了一些经典的字符和动画效果来模拟一个在控制台中显示的进度条。下面我将逐步解析代码,并解释每个部分的功能。
代码解析
void progressBar()
{char s[5] = "|/-\\"; // 旋转动画符号的数组char bar[NUM]; // 用于存储进度条符号的数组memset(bar, '\0', sizeof(bar)); // 将 bar 数组初始化为空字符int cnt = 0; // 进度计数int len = sizeof(s); // 符号数组 s 的长度while (cnt <= 100) // 循环直到进度达到 100{// 打印进度条printf("[%-100s][%d%%][%c]\r", bar, cnt, s[cnt % len]);fflush(stdout); // 强制刷新输出缓冲区,确保进度条即时显示bar[cnt++] = STYLE; // 在进度条的当前位置填入一个符号usleep(100000); // 休眠 100 毫秒}printf("\n"); // 输出换行符,表示进度条结束
}
代码详解
-
定义字符数组用于旋转动画 (
s[5] = "|/-\\"
):char s[5] = "|/-\\";
:s
数组包含了四个不同的字符符号:'|'
、'/'
、'-'
、'\\'
,这四个符号会在进度条的动画中轮流显示,制造一种旋转的效果。
-
初始化进度条字符串 (
bar[NUM]
):char bar[NUM];
:bar
用于存储进度条的状态,其中每个字符代表进度条的一部分。NUM
需要预先定义,通常等于 101,以便存储100
个字符和一个结束符'\0'
。memset(bar, '\0', sizeof(bar));
:使用memset
将整个bar
数组初始化为'\0'
,确保没有多余字符影响输出。
-
进度条循环 (
while(cnt <= 100)
):while(cnt <= 100)
:这个循环从 0 到 100,表示进度百分比从 0% 逐步增加到 100%。
-
显示进度条 (
printf
):printf("[%-100s][%d%%][%c]\r", bar, cnt, s[cnt % len]);
[%-100s]
:输出长度为 100 的字符串,%-
表示左对齐,所以进度条会从左到右扩展。[cnt%]
:显示当前进度百分比。[s[cnt % len]]
:这个部分用于动画效果,通过cnt % len
的余数来取s
数组中的字符,实现旋转动画。\r
:回车符,将光标返回到当前行的开头,以便刷新这行内容,达到更新进度条的效果。
-
刷新输出缓冲区 (
fflush(stdout)
):fflush(stdout);
:刷新标准输出缓冲区,确保printf
的内容能够立即显示到控制台,而不会被缓存。
-
更新进度条 (
bar[cnt++] = STYLE
):bar[cnt++] = STYLE;
:STYLE
应该是一个宏定义,用于表示进度条填充的符号。例如,可以定义STYLE
为:
每次循环,#define STYLE '='
bar
中对应的位置会填入STYLE
,逐步扩展进度条的长度。
-
休眠 (
usleep(100000)
):usleep(100000);
:让程序暂停100000
微秒(即100
毫秒),控制进度条的更新速度,避免其变化过快看不清。
-
打印结束的换行符 (
printf("\n")
):printf("\n");
:当进度到达 100% 时,打印一个换行符,使光标移到下一行,避免与后续输出混淆。
代码中的注意事项
-
NUM
的定义:- 需要预先定义
NUM
,通常设置为 101 来存储100
个字符的进度条和一个结束符\0
。例如:#define NUM 101
- 需要预先定义
-
STYLE
的定义:- 进度条的填充符号
STYLE
也需要定义。例如,可以这样定义:#define STYLE '='
- 进度条的填充符号
进度条和一个结束符 \0
。例如:
c #define NUM 101
STYLE
的定义:- 进度条的填充符号
STYLE
也需要定义。例如,可以这样定义:#define STYLE '='
- 进度条的填充符号