Linux基础-Makefile的编写、以及编写第一个Linux程序:进度条(模拟在 方便下载的同时,更新图形化界面)

目录

一、Linux项目自动化构建工具-make/Makefile

​编辑

背景:

makefile小技巧:

二、Linux第一个小程序-进度条

先导:

1.如何利用/r,fflush(stdout)来实现我们想要的效果;

2.写一个倒计时:

进度条:

version1:一个普通的进度条

version2:具体的应用场景,模拟下载软件

version3:在未来,方便下载的同时,更新图形化界面

代码:version3:

processbar.c:

processbar.h:

Main.c:


进度条完整代码在文章末尾

一、Linux项目自动化构建工具-make/Makefile

如图:让我们简单的来看一下makefile具有什么功能

你可以随意创建一个可运行的代码

在Makefile中

mytest:test.cgcc -o mytest test.c
.PHONY:clean
clean:rm -f mytest

然后:

makefile是一个文件,make是一个命令。

背景:

1.会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
2.一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
3.makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
4.make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
5.make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。

依赖关系:

$表示:取内容 

code.exe依赖于code.c

$@---目标文件

$^----整个依赖文件列表

注意:在makefile内的注释是#

如图:我们在makefile中这样写到

code.exe:code.ogcc code.o -o code.exe
code.o:code.sgcc -c code.s -o code.o
code.s:code.igcc -S code.i -o code.s
code.i:code.cgcc -E code.c -o code.i
.PHONY:clean
clean:rm -f code.i code.s code.o code.exe

makefile从上往下识别,而识别到code.o时,code.o并不存在,就不会执行该命令,继续往下识别,知道识别到code.c时,执行code.c的命令,再倒序执行。

一定要把最终需形成的文件放置开头

makefile小技巧:

makefile支持变量:

在执行程序时,隐藏命令

在使用makefile时,依赖方法只能有一行吗?可以有多行

我们不想显示这些命令:


二、Linux第一个小程序-进度条

\r&&\n
回车概念
换行概念
老式打字机的例子

我们键盘上的Enter键就相当于回车+换行 \r\n

先导:

1.如何利用/r,fflush(stdout)来实现我们想要的效果;

如图:我在test.c和makefile文件中写入这样的代码

打印后程序休眠3s,结束程序

test.c:

#include<stdio.h>int main()
{printf("hello zz,hello world...\n");return 0;
}

makefile:

bin=test.exe
src=test.c$(bin):$(src)@gcc -o $@ $^@echo "complier &(src) to &(bin)..."
.PHONY:clean
clean:@rm -f $(bin)@echo "clean project..."

同上:

3s后再打印,程序退出同时,打印。(未打印时,不代表程序没执行,只是放于缓冲区了)

提问:printf和sleep哪个函数先运行?printf先运行,由于执行代码是从上至下。

一般只有缓冲区满的时候,程序结束的时候,才会刷新缓冲区,因此在这里我们用到fflush函数强制刷新。

查阅手册:

修改代码后:

2.写一个倒计时:

在test.c中写到:

#include<stdio.h>
#include<unistd.h>int main()
{int cnt = 10;while(cnt >= 0){printf("%d\r",cnt);fflush(stdout);--cnt;sleep(1);}printf("\n");return 0;
}

实际上当我们运行程序时,会出现一个问题,明明打印的是10 - 0,但是,却变成从10、90、80....

这是因为,打印在显示器上的都是字符,当10时是两个字符,而当变为9后,只有一个字符,0无法被覆盖,则会一直被打印,解决办法:%2d

执行这个代码后,就会直接覆盖两个字符。

#include<stdio.h>
#include<unistd.h>int main()
{int cnt = 10;while(cnt >= 0){printf("倒计时: %2d\r",cnt);fflush(stdout);--cnt;sleep(1);}printf("\n");return 0;
}

进度条:

version1:一个普通的进度条

processbar--processbar.c--processbar.h--Main.c

然后在makefile中写到:

 processbar:Main.c processbar.cgcc -o $@ $^.PHONY:cleanclean:rm -f processbar   

processbar.c--processbar.h--Main.c分别写到:

processbar.c--processbar.h--Main.c

processbar.c:

   #include"processbar.h"                                                                                                         #include<string.h>                                                                                                          #include<unistd.h>                                                                                                          #define Length 101                                                                                                          #define Style '#'                                                                                                          const char *lable = "|/-\\";                                                                                                          void Procbar()                                                                                                          {                                                                                                                                 char bar[Length];                                                                                                          memset(bar,'\0',sizeof(bar));                                                                                                          int len = strlen(lable);                                                                                                                               int cnt = 0;                                                                                                          while(cnt <= 100)                                                                                                          {                                                                                                          printf("[%-100s][%2d%%][%c]\r",bar,cnt,lable[cnt%len]);  fllush(stdout);                                                                             bar[cnt++] = Style;                                                                                               usleep(50000);                                                                                                               }                                                                                                                         printf("\n");                                                                                              }                                                                                                                        

usleep,相当于原来sleep的10^-6,因此在这里代表将原本的100s缩短为5s完成

之后会输出这样的结果:

当然这样还不够完美:

version2:具体的应用场景,模拟下载软件

在Main.c

#include"processbar.h"
#include<unistd.h>//download
void download()
{double filesize = 100*1024*1024;//100Mdouble current = 0.0;double bandwidth = 1024*1024*1.0;printf("download begin,current: %lf\n",current);while(current <= filesize){Procbar(filesize,current);//从网络中获取数据current += bandwidth;usleep(50000);}printf("\ndownload done, filesize:%lf\n",filesize);
}int main()
{//Procbar(100.0,56.9);//Procbar(100.0,1.0);//Procbar(100.0,99.9);//Procbar(100.0,100);download();return 0;
}

在processbar.c中:

#include"processbar.h"
#include<string.h>
#include<unistd.h>#define Length 101
#define Style '#'
const char *lable = "|/-\\";
void Procbar(double total,double current)
{char bar[Length];memset(bar,'\0',sizeof(bar));int len = strlen(lable);int cnt = 0;double rate = (current * 100.0)/total; int loop_count = (int)rate;while(cnt <= loop_count){printf("[%-100s][%.1lf%%][%c]\r",bar,rate,lable[cnt%len]);fflush(stdout);bar[cnt++] = Style;}printf("\n");
}

这样却是一行一行的输出:

其实是因为

最后:

更优processbar.c代码:

#include"processbar.h"
#include<string.h>
#include<unistd.h>#define Length 101
#define Style '#'
const char *lable = "|/-\\";
void Procbar(double total,double current)
{char bar[Length];memset(bar,'\0',sizeof(bar));int len = strlen(lable);int cnt = 0;double rate = (current * 100.0)/total; int loop_count = (int)rate;while(cnt <= loop_count){// printf("[%-100s][%.1f%][%c]\r",bar,rate,lable[cnt%len]);// fflush(stdout);bar[cnt++] = Style;}printf("[%-100s][%.1f%][%c]\r",bar,rate,lable[cnt%len]);fflush(stdout);
}

version3:在未来,方便下载的同时,更新图形化界面

Main.c:

#include"processbar.h"
#include<unistd.h>//download
void download(callback_t cb)
{double filesize = 100*1024*1024;//100Mdouble current = 0.0;double bandwidth = 1024*1024*1.0;printf("download begin,current: %lf\n",current);while(current <= filesize){cb(filesize,current);//从网络中获取数据current += bandwidth;usleep(50000);}printf("\ndownload done, filesize:%lf\n",filesize);
}int main()
{//Procbar(100.0,56.9);//Procbar(100.0,1.0);//Procbar(100.0,99.9);//Procbar(100.0,100);download(Procbar);return 0;
}

processbar.h:

#pragma once
#include<stdio.h>
#include<unistd.h>//void Procbar();
typedef void(*callback_t)(double ,double );
void Procbar(double total,double current);

再更新

#include"processbar.h"
#include<unistd.h>
double bandwidth = 1024*1024*1.0;
//download
void download(double filesize,callback_t cb)
{//double filesize = 100*1024*1024;//100Mdouble current = 0.0;printf("download begin,current: %lf\n",current);while(current <= filesize){cb(filesize,current);//从网络中获取数据current += bandwidth;usleep(50000);}printf("\ndownload done, filesize:%lf\n",filesize);
}int main()
{//Procbar(100.0,56.9);//Procbar(100.0,1.0);//Procbar(100.0,99.9);//Procbar(100.0,100);download(100*1024*1024,Procbar);download(10*1024*1024,Procbar);download(99*1024*1024,Procbar);download(900*1024*1024,Procbar);return 0;
}

最后:


代码:version3:

processbar.c:

#include"processbar.h"
#include<string.h>
#include<unistd.h>#define Length 101
#define Style '#'
const char *lable = "|/-\\";
void Procbar(double total,double current)
{char bar[Length];memset(bar,'\0',sizeof(bar));int len = strlen(lable);int cnt = 0;double rate = (current * 100.0)/total; int loop_count = (int)rate;while(cnt <= loop_count){// printf("[%-100s][%.1f%][%c]\r",bar,rate,lable[cnt%len]);// fflush(stdout);bar[cnt++] = Style;}printf("[%-100s][%.1f%][%c]\r",bar,rate,lable[cnt%len]);fflush(stdout);
}

processbar.h:

#pragma once
#include<stdio.h>
#include<unistd.h>//void Procbar();
typedef void(*callback_t)(double ,double );
void Procbar(double total,double current);

Main.c:

#include"processbar.h"
#include<unistd.h>
double bandwidth = 1024*1024*1.0;
//download
void download(double filesize,callback_t cb)
{//double filesize = 100*1024*1024;//100Mdouble current = 0.0;printf("download begin,current: %lf\n",current);while(current <= filesize){cb(filesize,current);//从网络中获取数据current += bandwidth;usleep(50000);}printf("\ndownload done, filesize:%lf\n",filesize);
}int main()
{//Procbar(100.0,56.9);//Procbar(100.0,1.0);//Procbar(100.0,99.9);//Procbar(100.0,100);download(100*1024*1024,Procbar);download(10*1024*1024,Procbar);download(99*1024*1024,Procbar);download(900*1024*1024,Procbar);return 0;
}

结语:

       随着这篇关于题目解析的博客接近尾声,我衷心希望我所分享的内容能为你带来一些启发和帮助。学习和理解的过程往往充满挑战,但正是这些挑战让我们不断成长和进步。我在准备这篇文章时,也深刻体会到了学习与分享的乐趣。

       在此,我要特别感谢每一位阅读到这里的你。是你的关注和支持,给予了我持续写作和分享的动力。我深知,无论我在某个领域有多少见解,都离不开大家的鼓励与指正。因此,如果你在阅读过程中有任何疑问、建议或是发现了文章中的不足之处,都欢迎你慷慨赐教。         你的每一条反馈都是我前进路上的宝贵财富。同时,我也非常期待能够得到你的点赞、收藏,关注这将是对我莫大的支持和鼓励。当然,我更期待的是能够持续为你带来有价值的内容,让我们在知识的道路上共同前行

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智能家居环境监测系统设计(论文+源码)

1. 系统方案 系统由9个部分构成&#xff0c;分别是电源模块、烟雾传感器模块、GSM发送短信模块、报警模块、温度传感器模块、人体红外感应模块、按键设置模块、显示模块、MCU模块。各模块的作用如下&#xff1a;电源模块为系统提供电力&#xff1b;烟雾传感器模块检测烟雾浓度&…

猫狗识别大模型——基于python语言

目录 1.猫狗识别 2.数据集介绍 3.猫狗识别核心原理 4.程序思路 4.1数据文件框架 4.2 训练模型 4.3 模型使用 4.4 识别结果 5.总结 1.猫狗识别 人可以直接分辨出图片里的动物是猫还是狗&#xff0c;但是电脑不可以&#xff0c;要想让电脑也分辨出图片里的动物是猫还是小…

C++面试3

一、常用设计模式 https://blog.csdn.net/m0_71530237/article/details/141140118?spm1001.2014.3001.5501 二、死锁以及解决方式&#xff1f; 死锁&#xff1a;一种常见的并发问题&#xff0c;发生在多个进程或线程因为竞争资源而陷入相互等待的状态&#xff0c;导致这些进…

Flutter之SystemChrome全局设置

一、简介 SystemChrome作为一个全局属性&#xff0c;很像 Android 的 Application&#xff0c;功能很强大。 二、使用详解 2.1 setPreferredOrientations 设置屏幕方向 在我们日常应用中可能会需要设置横竖屏或锁定单方向屏幕等不同要求&#xff0c;通过 setPreferredOrien…

JavaScript高级——作用域和作用链

1、概念理解&#xff1a; —— 就是一块“地盘”&#xff0c;一个代码所在的区域 —— 静态的&#xff08;相对于上下文对象&#xff09;&#xff0c;在编写代码时就确定了 2、分类 ① 全局作用域 ② 函数作用域 ③ 没有块作用域&#xff08;ES6有了&#xff09; 3、作用 …

WPF利用Path自定义画头部导航条(TOP)样式

1;新建两个多值转换器&#xff0c;都有用处&#xff0c;用来动态确定PATH的X,Y州坐标的。 EndPointConverter 该转换器主要用来动态确定X轴&#xff0c;和Y轴。用于画线条的。 internal class EndPointConverter : IMultiValueConverter {public object Convert(object[] val…

GIS 中的 3D 分析

GIS 中的 3D 分析 3D 分析已成为 GIS 的一个发展趋势&#xff0c;因为它能够更好地表现现实世界。 这不仅仅是为了得到漂亮的图片。对于某些类型的问题&#xff0c;3D 分析有时是解决它们的唯一方法。 3D 数据类型的激增也推动了这一需求。例如&#xff0c;LiDAR、BIM、UAV、…

VS Code 配置 Rust-Analyzer 报错

报错信息&#xff1a; Bootstrap Error" rust-analyzer requires glibc > 2.28 in latest build. 参考了好多地方&#xff0c; https://github.com/rust-lang/rust-analyzer/issues/11558 https://blog.csdn.net/aLingYun/article/details/120923694 https://rust-anal…

C++——⼆叉搜索树

文章目录 一、 ⼆叉搜索树的概念二、⼆叉搜索树的性能分析三、⼆叉搜索树的插⼊四、⼆叉搜索树的查找五、⼆叉搜索树的删除六、二叉搜索树的有序遍历七、⼆叉搜索树的实现代码八、二叉搜索树key与key_value的应用key的应用key_value的应用key/value⼆叉搜索树代码实现 一、 ⼆叉…

C++类与对象深度解析(一):从抽象到实践的全面入门指南

文章目录 C 类与对象——详细入门指南前言1. 类的定义1.1 类定义的基本格式示例代码解释 1.2 访问限定符示例代码解释 1.3 类域示例代码解释 1.4 成员命名规范常见的命名约定&#xff1a;示例&#xff1a;拓展&#xff1a; 1.5 class与struct的默认访问权限示例&#xff1a; 2.…

搭建Windows下的Rust开发环境

【图书介绍】《Rust编程与项目实战》-CSDN博客 《Rust编程与项目实战》(朱文伟&#xff0c;李建英)【摘要 书评 试读】- 京东图书 (jd.com) Rust编程与项目实战_夏天又到了的博客-CSDN博客 2.1.1 安装vs_buildtools 在Windows系列操作系统中&#xff0c;Rust开发环境需要依…

归并排序(Merge Sort)

什么是归并排序 归并排序&#xff08;Merge Sort&#xff09;是一种经典的排序算法&#xff0c;它采用分治法&#xff08;Divide and Conquer&#xff09;策略&#xff0c;将一个大数组分为两个小数组&#xff0c;分别进行排序&#xff0c;然后将这两个已排序的小数组合并成一个…

音视频开发常见的开源项目汇总

FFmpeg 地址&#xff1a;https://ffmpeg.org/介绍&#xff1a;FFmpeg 是一个非常强大的开源多媒体框架&#xff0c;它可以用来处理视频和音频文件。它支持多种格式的转换、编码、解码、转码、流处理等。FFmpeg 包括了 libavformat、libavcodec、libavutil、libswscale、libpos…

组播 2024 9 11

PIM&#xff08;Protocol Independent Multicast&#xff09;是一种常用的组播路由协议&#xff0c;其独立于底层的单播路由协议&#xff0c;能够在多种网络环境中有效地实现多播路由功能。PIM主要有两种模式&#xff1a;PIM Sparse Mode (PIM-SM) 和 PIM Dense Mode (PIM-DM)&…

【C++题解】1580. 扫雷(mine)

欢迎关注本专栏《C从零基础到信奥赛入门级&#xff08;CSP-J&#xff09;》 问题&#xff1a;1580. 扫雷&#xff08;mine&#xff09; 类型&#xff1a;二维数组 题目描述&#xff1a; 扫雷游戏是一款十分经典的单机小游戏。在 n 行 m 列的雷区中有一些格子含有地雷&#x…

I/O 多路复用:`select`、`poll`、`epoll` 和 `kqueue` 的区别与示例

I/O 多路复用是指在一个线程内同时监控多个文件描述符&#xff08;File Descriptor, FD&#xff09;&#xff0c;以便高效地处理多个 I/O 事件。在 UNIX/Linux 和 BSD 系统中&#xff0c;select、poll、epoll、kqueue 都是实现 I/O 多路复用的系统调用。它们各有特点&#xff0…

el-input设置type=‘number‘和v-model.number的区别

el-input设置typenumber’与设置.number修饰符的区别 1. 设置type‘number’ 使用el-input时想收集数字类型的数据&#xff0c;我们首先会想到typenumber&#xff0c;设置完type为number时会限制我们输入的内容只能为数字&#xff0c;不能为字符/汉字等非数字类型的数值&…

性能诊断的方法(五):架构和业务诊断

关于性能诊断的方法&#xff0c;我们可以按照“问题现象—直接原因—问题根源”这样一个思路去归纳。我们先从问题的现象去入手&#xff0c;包括时间的分析、资源的分析和异常信息的分析。接下来再去分析产生问题现象的直接原因是什么&#xff0c;这里我们归纳了自上而下的资源…

外观模式详解:如何为复杂系统构建简洁的接口

&#x1f3af; 设计模式专栏&#xff0c;持续更新中 欢迎订阅&#xff1a;JAVA实现设计模式 &#x1f6e0;️ 希望小伙伴们一键三连&#xff0c;有问题私信都会回复&#xff0c;或者在评论区直接发言 外观模式 外观模式&#xff08;Facade Pattern&#xff09;为子系统中的一组…

linux系统安装miniconda3

一、下载minconda3 下载地址&#xff1a;https://docs.conda.io/en/latest/miniconda.html 一般国内访问比较困难&#xff0c;可到清华软件镜像站 Index of /anaconda/miniconda/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 需要特别注意自己的下载版本和自己的…