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;
}
结语:
随着这篇关于题目解析的博客接近尾声,我衷心希望我所分享的内容能为你带来一些启发和帮助。学习和理解的过程往往充满挑战,但正是这些挑战让我们不断成长和进步。我在准备这篇文章时,也深刻体会到了学习与分享的乐趣。
在此,我要特别感谢每一位阅读到这里的你。是你的关注和支持,给予了我持续写作和分享的动力。我深知,无论我在某个领域有多少见解,都离不开大家的鼓励与指正。因此,如果你在阅读过程中有任何疑问、建议或是发现了文章中的不足之处,都欢迎你慷慨赐教。 你的每一条反馈都是我前进路上的宝贵财富。同时,我也非常期待能够得到你的点赞、收藏,关注这将是对我莫大的支持和鼓励。当然,我更期待的是能够持续为你带来有价值的内容,让我们在知识的道路上共同前行
相关文章:

Linux基础-Makefile的编写、以及编写第一个Linux程序:进度条(模拟在 方便下载的同时,更新图形化界面)
目录 一、Linux项目自动化构建工具-make/Makefile 编辑 背景: makefile小技巧: 二、Linux第一个小程序-进度条 先导: 1.如何利用/r,fflush(stdout)来实现我们想要的效果; 2.写一个倒计时: 进度条…...

华为云DevSecOps和DevOps
目录 1.华为云DevSecOps和DevOps 1.1 DevSecOps 1.1.1 核心功能 1.1.2 优势 1.2 DevOps 1.2.1 核心功能 1.2.2 优势 1.3 DevOps和DevSecOps的区别 1.3.1 安全性集成 1.3.2 自动化的安全工具 1.3.3 团队协作 1.3.4 质量与合规性 1.3.5 成本与风险管理 1.3.5 总结 …...

RESTful API设计中的GET与POST:何时及为何成为首选?
RESTful API设计中的GET与POST:何时及为何成为首选? 在RESTful API的设计过程中,HTTP方法(GET、POST、PUT、DELETE等)作为资源的操作标识,扮演着至关重要的角色。然而,在实际开发中,…...

秋招自我介绍
1min 尊敬的面试官您好,感谢您百忙之中参加我的面试。我是来自北京大学的王峰。 在实习经历方面,我曾在美团和小米公司实习。在美团主要负责核身、质检、词云项目。 在核身项目中,完整的经历从0-1的项目上线过程 在质检项目中,进…...

html加载页面
<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>算数模一体化</title> </head><b…...

【数据可视化】Arcgis api4.x 热力图、时间动态热力图、timeSlider时间滑块控件应用 (超详细、附免费教学数据、收藏!)
1.效果 目录 1.效果 2.安装配置 3.热力图 4.TimeSlider滑块应用 4.1 时间滑块控件 4.2 添加控件 5.时间动态热力图 2.安装配置 这里不教大家如何在前端框架使用arcgis api。不过npm安装、css如何引入、教学数据存放与图层加载的教程,可以浏览我之前发的一篇文…...

WEB攻防-JavaWweb项目JWT身份攻击组件安全访问控制
知识点: 1、JavaWeb常见安全及代码逻辑; 2、目录遍历&身份验证&逻辑&JWT; 3、访问控制&安全组件&越权&三方组件; 演示案例: JavaWeb-WebGoat8靶场搭建使用 安全问题-目录遍历&身份认…...

【C++算法】模拟算法
替换所有的问号 题目链接 替换所有的问号https://leetcode.cn/problems/replace-all-s-to-avoid-consecutive-repeating-characters/description/ 算法原理 代码步骤 class Solution { public:string modifyString(string s) {int n s.size();for(int i 0; i < n; i){…...

模版进阶(template)
1.非类型模版参数 模版参数分类类型形参与非类型形参。 ① 类型形参:出现在在模板参数列表中,跟在class或者typename之类的参数类型名称。 ② 非类型形参,就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当…...

vue2与vue3的区别
1.v-if与v-for的优先级不同 2.vue2中存在数据更新以后视频不更新的问题,故存在$set来解决这一问题,而vue3中数据双向绑定不存在数据更新视图不更新的问题,所以也就没有this.$set...

借助大模型将文档转换为视频
利用传统手段将文档内容转换为视频,比如根据文档内容录制一个视频,不仅需要投入大量的时间和精力,而且往往需要具备专业的视频编辑技能。使用大模型技术可以更加有效且智能化地解决上述问题。本实践方案旨在依托大语言模型(Large …...

UE5安卓项目打包安装
Android studio安装 参考:https://docs.unrealengine.com/5.2/zh-CN/how-to-set-up-android-sdk-and-ndk-for-your-unreal-engine-development-environment/ 打开android studio的官网:Download Android Studio & App Tools - Android Developers …...

MSF的使用学习
一、更新MSF apt update # 更新安装包信息;只检查,不更新(已安装的软件包是否有可用的更新,给出汇总报告) apt upgrade # 更新已安装的软件包,不删除旧包; apt full-upgrade # 升级包&#x…...

C++ —— 关于vector
目录 链接 1. vector的定义 2. vector的构造 3. vector 的遍历 4. vector 的扩容机制 5. vector 的空间接口 5.1 resize 接口 5.2 push_back 5.3 insert 5.4 erase 5.5 流插入与流提取 vector 并不支持流插入与流提取,但是可以自己设计,更…...

设计模式——对象池模式
对象池模式 1. 概述2. 适用场景3. 原理4. 优点5. 缺点 示例代码示例代码使用示例 Java 标准库中的例子Apache Commons Pool 示例 1. 概述 对象池模式(Object Pool Pattern) 是一种用于管理和复用一组预先创建的对象的设计模式。它的主要目的是为了提高性…...

【VitualBox】VitualBox的网络模式+网络配置
VirtualBox 1. 简介 VirtualBox 是一款开源虚拟机软件,使用者可以在VirtualBox上安装并且执行Solaris、Windows、DOS、Linux、OS/2 Warp、BSD等系统作为客户端操作系统。 2. 六种网络接入模式 VirtualBox提供了多种网络接入模式,他们各有优缺点…...

「Netmarble 小镇」活动来了:踏上穿越标志性世界的旅程!
欢迎来到 Netmarble 小镇!本次活动从 9 月 13 日持续到 10 月 11 日,是你们体验 Netmarble 著名游戏世界最精彩内容的入口。在为期一个月的庆祝活动中,你们将体验到独家内容、惊险刺激的挑战和全新人物化身的发布! 探索 Netmarble…...

MySQL 中的索引覆盖扫描:加速查询的秘密武器
在 MySQL 数据库的使用中,索引是提高查询性能的重要工具。而索引覆盖扫描(Index Covering Scan)更是一种能显著提升查询效率的技术。本篇文章我们就来深入了解一下 MySQL 中的索引覆盖扫描是什么。 一、什么是索引覆盖扫描 在 MySQL 中&…...

【机器学习】经典数据集鸢尾花的分类识别
【机器学习】经典数据集鸢尾花的分类识别 1、数据集介绍1.1 数据集详情 2、实验内容2.1 准备数据集2.2 创建颜色映射对象2.3 绘制特征散点图2.4 数据的归一化2.5 数据的标准化 3、实验截图提取萼片长度与萼片宽度分类提取萼片长度与花瓣长度分类提取萼片长度与花瓣宽度分类提取…...

Oracle从入门到放弃
Oracle从入门到放弃 左连接和右连接Where子查询单行子查询多行子查询 from子句的子查询select子句的子查询oracle分页序列序列的应用 索引PL/SQL变量声明与赋值select into 赋值变量属性类型 异常循环游标存储函数存储过程不带传出参数的存储过程带传出参数的存储过程 左连接和…...

学习笔记 - 知识图谱的符号表示方法
学习笔记 - 知识图谱的符号表示方法 说明: 首次发表日期:2024-09-13个人阅读学习并摘录成笔记 知识表示的相关名词定义 以下内容摘录自 Knowledge Graphs Applied 2.3小节,然后AI翻译人工润色。 实体(Entities)—表…...

探索RESTful风格的网络请求:构建高效、可维护的API接口【后端 20】
探索RESTful风格的网络请求:构建高效、可维护的API接口 在当今的软件开发领域,RESTful(Representational State Transfer)风格的网络请求已经成为构建Web服务和API接口的标配。RESTful风格以其简洁、无状态、可缓存以及分层系统等…...

【深度智能】:迈向高级时代的人工智能全景指南
前几天偶然发现了一个超棒的人工智能学习网站,内容通俗易懂,讲解风趣幽默,简直让人欲罢不能。忍不住分享给大家,人工智能立刻跳转,开启你的AI学习之旅吧! 第一阶段:基础知识 1. 计算机科…...

unity3d入门教程七
unity3d入门教程七 17.1物理系统17.2静态刚体17.3刚体的碰撞17.4刚体的反弹18.1运动学刚体18.2碰撞检测18.3碰撞事件回调18.4目标的识别18.5碰撞的规避 17.1物理系统 在物理系统中的物体具有质量和速度的是刚体 不用写代码就会自由落体运动了 17.2静态刚体 给 ‘地面’ 添…...

python植物大战僵尸项目源码【免费】
植物大战僵尸是一款经典的塔防游戏,玩家通过种植各种植物来抵御僵尸的进攻。 源码下载地址: 植物大战僵尸项目源码 提取码: 8muq...

目前人工智能时代,程序员如何保持核心竞争力?
随着AIGC(如chatgpt、midjourney、claude等)大语言模型接二连三的涌现,AI辅助编程工具日益普及,程序员的工作方式正在发生深刻变革。有人担心AI可能取代部分编程工作,也有人认为AI是提高效率的得力助手。面对这一趋势,…...

golang学习笔记20——golang微服务负载均衡的问题与解决方案
推荐学习文档 golang应用级os框架,欢迎stargolang应用级os框架使用案例,欢迎star案例:基于golang开发的一款超有个性的旅游计划app经历golang实战大纲golang优秀开发常用开源库汇总想学习更多golang知识,这里有免费的golang学习笔…...

基于微信小程序的健身房管理系统
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 基于微信小程序JavaSpringBootVueMySQL的健…...

【裸机装机系列】6.kali(ubuntu)-图形界面优化-让linux更适合你的使用习惯
接下来就是图形化界面操作的部分了。会用少量截图来说明,图太多会影响阅读体验,直接文字来描述过程吧。 1> 入口 任务栏左上角——> 开始菜单——> settings——> settings manager 大部分配置都会在这里面设置。 2> 设置里面分的4大…...

新的突破,如何让AI与人类对话变得“顺滑”:Moshi背后的黑科技
你有没有想过,当我们跟智能音箱、客服机器人或者语音助手对话时,它们是怎么“听懂”我们说的话,又是怎么迅速给出回应的?就好像你对着Siri、Alexa说一句:“给我订个披萨”,它立刻明白你想要干嘛,然后帮你下单。背后的技术其实比我们想象的要复杂得多,但现在,有了Moshi…...