当前位置: 首页 > article >正文

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.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.kler.cn/a/305243.html

相关文章:

  • uni-app中使用 unicloud 云开发平台③
  • HarmonyOS ArkTS 下拉列表组件
  • 【leetcode练习·二叉树】用「分解问题」思维解题 II
  • 【GPTs】MJ Prompt Creator:轻松生成创意Midjourney提示词
  • 鸿蒙next版开发:ArkTS组件通用属性(Z序控制)
  • ReactPress:构建高效、灵活、可扩展的开源发布平台
  • ubuntu 22.04 ~24.04 如何修改登录背景
  • 【JavaScript】LeetCode:707设计链表
  • Python版《天天酷跑+源码》,详细讲解,手把手教学-python游戏开发
  • jmeter设置全局token
  • (180)时序收敛--->(30)时序收敛三十
  • 大模型教程:使用 Milvus、vLLM 和 Llama 3.1 搭建 RAG 应用
  • 怎么让手机ip地址变化?介绍几种实用方法
  • uniapp 微信小程序自定义tabbar层级低于canvas解决方案
  • 见刊丨“GPU池化”术语发布
  • 本地内存和分布式缓存(面试)
  • Python Web 开发中的性能优化策略(二)
  • git 命令---想要更改远程仓库
  • 指针与函数传递
  • C++速通LeetCode简单第12题-二叉树的直径
  • 深度学习-目标检测(四)-Faster R-CNN
  • C#实现串口中继
  • 不废话简单易懂的Selenium 页面操作与切换
  • Python实现一个简单的爬虫程序(爬取图片)
  • postgresql 导出CSV格式数据
  • 电脑连手机热点,上不了网