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是一个文件,两个搭配使用,完成项目自动化构建。

依赖关系:

注意:在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.xdnf.cn/news/1534477.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

恭喜!龙蜥社区2024年中三大奖项评选名单新鲜出炉

近日&#xff0c;在 2024 龙蜥操作系统大会上&#xff0c;龙蜥社区公布了 2024 年中三大奖项评选名单——“最佳合作伙伴奖”“最佳用户案例奖”“最佳应用实践奖&#xff08;个人&#xff09;”&#xff0c;并邀请清华大学计算机系教授、龙蜥社区高级顾问史元春&#xff0c;海…

地市专利申请及授权数据集合(2000-2023年)xlsx+dta格式

包括发明专利、实用新型、外观专利的申请和授权等。专利作为衡量一个地区科技创新能力和水平的重要指标&#xff0c;不仅反映了地方企业在技术研发、产品创新方面的活跃程度&#xff0c;也是推动产业升级、促进经济高质量发展的关键力量 一、数据介绍 数据名称&#xff1a;地…

ImportError: DLL load failed while importing _ssl: 找不到指定的模块的解决方法

ImportError: DLL load failed while importing _ssl: 找不到指定的模块的解决方法 现象解决办法 现象 在命令行中&#xff0c;可以正常导入_ssl模块&#xff0c;如下&#xff1a; Python 3.9.0 (default, Nov 15 2020, 08:30:55) [MSC v.1916 64 bit (AMD64)] :: Anaconda, …

落地扶持丨云微客山西临汾落地会销圆满收官

2024年9月6日&#xff0c;云微客落地扶持走进山西临汾红星美凯龙《助力家居行业营销数智化研讨会》&#xff0c;活动吸引了近百家家居品牌商户的参与&#xff0c;现场气氛热烈&#xff0c;签约不断&#xff0c;为当地家居行业打开短视频矩阵营销新思路。 短视频成为全行业必争…

界面控件DevExpress中文教程:如何PDF图形对象的可见性?

DevExpress拥有.NET开发需要的所有平台控件&#xff0c;包含600多个UI控件、报表平台、DevExpress Dashboard eXpressApp 框架、适用于 Visual Studio的CodeRush等一系列辅助工具。屡获大奖的软件开发平台DevExpress 近期重要版本v24.1已正式发布&#xff0c;该版本拥有众多新产…

单机快速部署开源、免费的分布式任务调度系统——Apache DolphinScheduler

本文主要为大家介绍Apache DolphinScheduler的单机部署方式&#xff0c;方便大家快速体验。 环境准备 需要Java环境&#xff0c;这是一个老生常谈的问题&#xff0c;关于Java环境的安装与配置期望大家都可以熟练掌握。 验证java环境 java -version 下载安装包并解压 使用wg…

现代 Web 开发工具箱:Element-UI 表单组件全攻略(一)

现代 Web 开发工具箱&#xff1a;Element-UI 表单组件全攻略&#xff08;一&#xff09; 一 . Radio 单选框1.1 创建 Radio 按钮① 注册路由② 创建 radio 组件 1.2 Radio 的相关属性① 是否禁用② 是否显示边框③ 原生 name 属性④ 按钮的样式 1.3 Radio 相关事件1.4 Radio 按…

从 TF卡升级 f1c100s spinand

开发GUI 便宜好用的ARM 不多见了&#xff0c;f1c100s 作为首选&#xff0c;搜索相关spinand 启动支持 的uboot 帖子大多相当久远&#xff0c;随着uboot的升级 已经支持spinand 启动&#xff0c;但是spl 部分支持任然需要查询相关资料才行&#xff1b; 参考该博主文章&#xff…

Kubernetes从零到精通(07-工作负载-StatefulSet)

StatefulSet示例 正如Deployment管理无状态应用程序的资源&#xff0c;StatefulSet用来管理有状态应用程序&#xff08;如kafka、redis、zookeeper集群等&#xff09;的资源&#xff0c;它为每个 Pod 分配一个固定的名称和存储&#xff0c;以确保它们可以保留状态&#xff0c;无…

PHP仓库物资出入库管理系统小程序源码

仓库物资出入库管理系统&#xff1a;让库存管理变得井井有条 **&#x1f4e6; 开篇&#xff1a;告别混乱&#xff0c;拥抱智能库存时代 还在为仓库里堆积如山的物资和繁琐的出入库记录而头疼吗&#xff1f;是时候告别那些混乱的日子了&#xff01;“仓库物资出入库管理系统”应…

Redis的持久化和高可用性

目录 一、淘汰策略 1、背景 2、淘汰策略 二、持久化 1、背景 2、fork进程写时复制机制 3、Redis持久化方式 1、aof 2、rdb 三、高可用 1、主从复制 2、Redis哨兵模式 3、Redis cluster集群 一、淘汰策略 1、背景 首先Redis是一个内存数据库&#xff0c;将所有数…

【Python机器学习】序列到序列建模和注意力机制——编码-解码架构

LSTM非常擅长处理序列&#xff0c;但我们需要一对而不是一个LSTM。我们将构建一个模块化的架构&#xff0c;称为编码-解码架构。 编码-解码架构的前半部分是序列编码器&#xff0c;该网络将序列&#xff08;如自然语言文本&#xff09;转换为较低维的表示形式&#xff08;如思…

重生奇迹MU 红龙剑士的风采 游戏玩家的记忆

在重生奇迹MU游戏中&#xff0c;剑士是一个老牌职业&#xff0c;而其中红龙剑士更是备受瞩目的角色。红龙剑士选手身着一身红色龙王装&#xff0c;仿佛已经沐浴了敌人的鲜血&#xff0c;是一个经验丰富的剑手。很多老玩家都信任剑士这个职业&#xff0c;并视其为忠实的伙伴&…

[每周一更]-(第114期):介绍GitLab不同角色对应的权限

文章目录 GitLab 角色及其权限项目级别角色组级别角色 使用场景示例 工作中一直使用Gitlab搭建了公司内网的代码管理工具&#xff0c;但是不同的用户会分配相应的权限&#xff0c;来管理不同用户及角色的权限信息&#xff0c;我们来介绍下角色的信息&#xff0c;方便我们管理公…

C++教程(一):超详细的C++矩阵操作和运算(附实例代码,与python对比)

python教程&#xff08;一&#xff09;&#xff1a;超详细的numpy矩阵操作和运算&#xff08;附实例代码&#xff09; 在之前的章节中&#xff0c;我们详细介绍了python中numpy的矩阵操作。但在自动驾驶开发中&#xff0c;我们一般采用C进行功能开发&#xff0c;因此C矩阵运算…

重学SpringBoot3-集成RocketMQ(二)

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-集成RocketMQ&#xff08;二&#xff09; 1. 基础概念2. 准备工作3. 实现事务消息的生产者4. 事务监听器实现5. 消费者示例6. 发送事务消息7. 测试7.1 模…

【新片场-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…

如何用SQL Server和Oracle进行数据同步?

数据同步是大数据应用中非常重要的环节&#xff0c;它可以保证数据的实时性和一致性&#xff0c;为数据分析和决策提供重要依据。常见的数据同步方式包括ETL实时同步和实时ETL工具&#xff0c;其中实时ETL工具又可以分为基于日志追踪和基于触发器两种。 针对不同的数据库系统&…

在grafana上配置显示全部node资源信息概览

在grafana上配置显示全部node资源信息概览&#xff0c;便于巡检 1&#xff0c;注册grafana官网账号&#xff1a;Grafana dashboards | Grafana Labs&#xfeff; 2、寻找可以展示所有node资源概览信息的dashboard&#xff0c;并下载支持prometheus数据源的dashboard&#xff…

DevOps 中常常被忽略却至关重要的一个工具

在今天的云原生开发时代&#xff0c;DevOps 已经成为许多企业提高开发和运维效率的标准流程。DevOps 工具链广泛而复杂&#xff0c;涵盖了从规划、开发、测试到部署、监控和运维的多个环节。例如&#xff1a;规划与项目管理工具 GitLab、Jira&#xff1b;版本控制工具 Git&…