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

news2024/9/27 7:20:46

目录

一、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.c
    gcc -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.o
    gcc code.o -o code.exe
code.o:code.s
    gcc -c code.s -o code.o
code.s:code.i
    gcc -S code.i -o code.s
code.i:code.c
    gcc -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.c
   gcc -o $@ $^
 .PHONY:clean
 clean:
   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;//100M
  double 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;//100M
  double 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;//100M
  double 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;//100M
  double 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.coloradmin.cn/o/2137790.html

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

相关文章

[数据集][目标检测]智慧交通铁路人员危险行为躺站坐检测数据集VOC+YOLO格式3766张4类别

图片数量(jpg文件个数)&#xff1a;3766 标注数量(xml文件个数)&#xff1a;3766 标注数量(txt文件个数)&#xff1a;3766 标注类别数&#xff1a;4 标注类别名称:["sitting","sleeping","standing","track"] 每个类别标注的框数&…

可解释性机器学习中的局部解释

可解释性机器学习可以被分成两大类&#xff0c;第一大类叫做局部的解释&#xff0c;第二大类叫做全局的 解释&#xff0c;如图 1 所示。局部的解释是&#xff0c;比如有一个图像分类器&#xff0c;输入一张图片&#xff0c;它会判断出 是一只猫&#xff0c;机器要回答问题是为什…

微分方程人口模型以及Matlab代码实现

马尔萨斯模型 模型假设 1.设x(t)表示t时刻的人口数,且x(t)连续可微。 2.人口的增长率r是常数(增长率出生率-死亡率)。 3.人口数量的变化是封闭的,即没有人口迁移&#xff0c;且人口数量的增加与减少只取决于人口中个体的生育和死亡,且每一个体都具有同样的生育能力与死亡率。…

Parallels Desktop 20 for Mac中文版发布了?会哪些新功能

Parallels Desktop 20 for Mac 正式发布&#xff0c;完全支持 macOS Sequoia 和 Windows 11 24H2&#xff0c;并且在企业版中引入了全新的管理门户。 据介绍&#xff0c;新版本针对 Windows、macOS 和 Linux 虚拟机进行了大量更新&#xff0c;最大的亮点是全新推出的 Parallels…

项目升级必备!TS装饰器:简化代码、增加功能的利器 | TypeScript入门指南07

嘿&#xff0c;朋友&#xff01;听说过TS里的装饰器没&#xff1f;就像给代码加了个‘魔法贴’&#xff0c;轻轻一点&#xff0c;功能升级&#xff0c;结构清晰。这篇文章&#xff0c;咱们聊聊这背后的魔法是怎么一回事&#xff01; ts 入门指南系列 Ts vs Js 谁适合前端开发&a…

【笔记】位运算

文章目录 位运算简介与运算&或运算|异或运算^证明 取反~左移<<右移>> 位运算技巧判断奇偶性求出x二进制的第i位将二进制的第i位设置成1将二进制的第i位设置成0判断是否为2的若干次方获取x的最低位的1用lowbit运算统计1的个数例题 位运算简介 位运算&#xff1…

【吊打面试官系列-Redis面试题】使用过 Redis 分布式锁么,它是什么回事?

大家好&#xff0c;我是锋哥。今天分享关于【使用过 Redis 分布式锁么&#xff0c;它是什么回事&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; 使用过 Redis 分布式锁么&#xff0c;它是什么回事&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资…

对目录的操作、获取文件信息

目录 一、目录操作 二、获取文件的相关信息 1、演示获取文件的相关信息 2、注意事项和细节 一、目录操作 需求&#xff1a; 1&#xff09;创建一级目录 d://aaa 2&#xff09;创建多级目录 d://bbb//ccc 3&#xff09;删除目录 d://aaa和d://bbb//ccc import os# 1&am…

自定义AI模型的调优、部署与评测

为了让大语言模型的AI能力更贴近业务需求&#xff0c;本文详细介绍了在阿里云百炼创建自定义模型的最佳实践。即便不清楚大模型的技术细节&#xff0c;您也能按照本篇的操作指引创建一个有效的自定义模型&#xff0c;从而轻松地为业务场景添加大模型服务能力。 自定义模型概述…

深度学习数据集交通类常见图像分类、目标检测、分割图像数据集(深度学习数据集 - 交通类解决方案)

深度学习数据集 - 交通类解决方案 引言&#xff1a; 随着自动驾驶技术的发展以及智能交通系统的普及&#xff0c;对于高质量、多样化的交通数据集的需求日益增长。我们提供一系列精心准备的数据集&#xff0c;旨在帮助研究人员和工程师解决实际问题&#xff0c;推动技术创新。…

arcgisPro修改要素XY容差

1、在arcgisPro中XY容差的默认值为1个毫米&#xff0c;及0.001米。为了更精细的数据&#xff0c;需要提高这个精度&#xff0c;如何提高呢&#xff1f; 2、如果直接在数据库下新建要素类&#xff0c;容差只能调至0.0002米。所以&#xff0c;需要在数据库下新建要素数据集。 3…

机房运维工作的核心:确保系统稳定与高效

在当今的信息化时代&#xff0c;运维工作成为了确保企业信息系统稳定运行的关键环节。运维团队肩负着监控系统性能、处理故障、优化系统配置等多重任务&#xff0c;以确保平台的持续、高效运行。本文将围绕运维工作的几个核心方面展开讨论&#xff0c;并以监控易一体化运维软件…

【Linux下的cpp】编译调试(gcc、g++、gdb)

【Linux下的cpp】编译调试&#xff08;gcc、g、gdb&#xff09; 文章目录 【Linux下的cpp】编译调试&#xff08;gcc、g、gdb&#xff09;简述gcc、g、gdb编译过程g 编译参数命令行编译演练1、直接编译2、生成库文件并编译链接静态库并生成可执行文件链接动态库生成可执行文件 …

vue vueUse利用useInfiniteScroll API 实现虚拟滚动

前言 中文网地址:开始使用 | VueUse 中文网 官网地址:VueUse 元素的无限滚动。 useInfiniteScroll 详细解析地址 效果 组件封装

7-14 电话聊天狂人(map)

输入样例: 4 13005711862 13588625832 13505711862 13088625832 13588625832 18087925832 15005713862 13588625832输出样例: 13588625832 3 代码&#xff1a; #include<iostream> #include<map> using namespace std; map<string,int>mp; string ansstr;…

华为OD机试 - 推荐多样性(Python/JS/C/C++ 2024 E卷 100分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

nginx负载均衡(轮询与权重)

文章目录 1. nginx的介绍2. nginx使用场景3. nginx在windows的下载与安装4. nginx的简单使用5. nginx进行轮询测试6. nginx进行权重测试7. 总结 1. nginx的介绍 Nginx&#xff08;engine x&#xff09;是一个高性能的HTTP和反向代理web服务器&#xff0c;同时也是一个开源的、…

PASCAL VOC数据集语义分割:解决标签值错误与数据增强不同步问题的优化方案

创作不易&#xff0c;您的打赏、关注、点赞、收藏和转发是我坚持下去的动力&#xff01; 错误原因分析&#xff1a; Assertion错误&#xff1a; 错误信息显示 Assertion t > 0 && t < n_classes failed.&#xff0c;这意味着在计算损失时&#xff0c;标签t的值不…

第四天旅游线路预览——从换乘中心到喀纳斯湖

第四天&#xff1a;从贾登峪到喀纳斯风景区入口&#xff0c;晚上住宿贾登峪&#xff1b; 换乘中心有4 路车&#xff0c;喀纳斯①号车&#xff0c;去喀纳斯湖&#xff0c;路程时长约5分钟&#xff1b; 将上面的的行程安排进行动态展示&#xff0c;具体步骤见”Google earth stu…

【devops】devops-git之github使用

本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》&#xff1a;python零基础入门学习 《python运维脚本》&#xff1a; python运维脚本实践 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8…