【Linux第三课-基础开发工具的使用】yum、vim、gcc/g++编译器、gdb、Make/Makefile编写、进度条程序

一、 yum

快速认识yum

Linux中我们也要进行工具/指令/程序,安装、检查、卸载等,需要yum的软件
安装软件的方式:
1、源代码安装 – 交叉编译的工作
2、rpm包直接安装
3、yum / apt-get
yum是我们Linux上的一条指令,搜索、下载、安装对应的软件
yum相当于是Linux的应用商店!

快速使用yum

yum list //列举yum可以安装的东西

yum搜索

yum list | grep lrzsz

yum安装

yum是先下载再安装

yum install 文件名
yum -y install 文件名

yum卸载

yum remove 文件名

-y:对于一些询问表示yes

yum -y remove 文件名

yum的周边 - yum的整个生态问题

在这里插入图片描述
1、yum如何得知目标服务器的地址和下载链接?
配置文件里面会记录下载的地址

ls /etc/yum.repos.d/

这里面对应的都是yum的本地仓库名
在这里插入图片描述
其中CentOS-Base.repo就是yum源,可以更改yum源
在这里插入图片描述
扩展软件源

yum install -y epel-release

2、云服务器谁提供的?
既得利益者提供的
3、谁提供软件?
大家愿意写的人开发的

二、 vim

写代码:vim
编代码:gcc/g++
调代码:gdb
维护项目结构、自动化编译:make/makefile

快速介绍vim

vim是一款多模式的编辑器,vim里面还有很多的子命令,来进行代码的编写操作
1、进入vim后一般没法写入,需要模式切换,i – insert插入模式
在这里插入图片描述

2、写完后按esc退出插入模式 -> shift+;(也就是:)进入低行模式 -> wq(保存并退出)-> 回车
在这里插入图片描述
3、gcc编译,运行
在这里插入图片描述

vim的模式

在这里插入图片描述

命令模式

插入模式 -> 命令模式:esc

插入模式

命令模式 -> 插入模式 :i/a/o

低行模式

命令模式 -> 低行模式:shift + ;(也就是:)
低行模式 -> 命令模式:esc

常见模式 – 命令、低行

命令模式 – 光标的移动

将光标定位到最右侧结尾处:shift+4($)
将光标定位到最左侧开头处:shift+6(^)
将光标定位到文本的最后一行:shift+g(G)
将光标定位到文本的最开始一行:gg
将光标定位到特定一行,例如第五行:5 shift g
h:左
j:下
k:上
l:右
w:以单词为单位向移动
b:以单词为单位向移动

命令模式 – 复制粘贴、剪贴、删除

n+yy:复制所在行/多行
n+p:在下一行进行粘贴一次/n次
u:撤销编辑操作,undo
ctrl+r:对刚刚的撤销进行撤销
n+dd:删除/剪切当前行/多行
dd、p:剪切

命令模式 – 小写/大写

shift+`(~):大小写快速切换

替换模式

n+r:替换当前光标所在字符/n个字符
shift+r:替换模式
在这里插入图片描述

命令模式 – 删除

n+x:删除光标所在字符/后面n个字符(往后删)
n+shift+x:往前删

命令模式 – 查找

shift+3(#):高亮要查找的函数名
n:下一个查找到的函数名/字符串

低行模式

wq:报存并退出
w!:强制写
q!:强制退出
wq!:强制保存并退出
!指令:可以在低行模式执行shell指令
/搜索的内容:
?搜索的内容
vs 文件名:会形成一个并在旁边对比
set nu:调出行号
set nonu:取消行号
vim test.c 行号:光标直接定位到指定行
shift+zz:保存并退出vim(不建议用)
在这里插入图片描述
光标在哪个窗口就是在编辑哪个窗口
在这里插入图片描述

在这里插入图片描述

多窗口的光标移动

ctrl+ww

批量化注释/去注释

批量化注释
1、ctrl+v:进入VISUAL BLOCK模式
2、按hjkl进行区域选择
3、shift+i:从VISUAL BLOCK模式切换成插入模式
4、//
5、按esc
在这里插入图片描述
批量化去注释
1、ctrl+v:进入VISUAL BLOCK模式
2、hjkl选择区域
3、按d
在这里插入图片描述

配置问题

1、进入用户家目录下
在这里插入图片描述
2、创建.vimrc
每个用户都有各自的.vimrc
在这里插入图片描述
3、vim .vimrc进行配置

set nu               //显示行号
set cursorline       //突出显示当前行
hi Cursorline cterm=bold ctermbg=black ctermfg=green guibg=green   //粗体显示选中行,用黑色框,字体标绿
set cursorcolum      //设置列高亮
set autoindent       //自动缩进
set softtabstop=4    //统一缩进为4
set tabstop=4        //tab缩进为4 
set cindent
set shiftwidth=4
set smartindent      //提供自动缩进
syntax on            //语法高亮 

inoremap ' ''<ESC>i  //自动补齐
inoremap " ""<ESC>i
inoremap < <><ESC>i
inoremap ( ()<ESC>i
inoremap [ []<ESC>i
inoremap { {<CR>}<ESC>O

简便配置方法:
curl -sLf https://gitee.com/HGtz2222/VimForCpp/raw/master/install.sh -o ./install.sh && bash ./install.sh
一定在普通账号下运行

解决sudo的白名单

在这里插入图片描述
在这里插入图片描述
得用root账户改

vim /etc/sudoers

root在写完退出wq的时候会显示没有这个权限,我们可以强制写入w!和q!强制退出

在这里插入图片描述
在这里插入图片描述

root用户和普通用户之间的切换

在这里插入图片描述

三、 gcc/g++

安装

sudo yum -y install gcc gcc-c++ autoconf make

程序的翻译过程及gcc选项

编译C语言是默认是a.out,如果想要指定名称的话,下列两种方法。
默认形成
在这里插入图片描述
指定名称
在这里插入图片描述
在这里插入图片描述
凡是和 -o 紧邻的是形成的可执行程序

  1  #include <stdio.h>
  2 #define M 100
  3 
  4 int main()
  5 {
  6     printf("hello linux\n");
  7     printf("hello linux: %d\n", M);                                                                                                                                 
  8     //printf("hello linux\n");
  9     //printf("hello linux\n");
 10     //printf("hello linux\n");
 11     //printf("hello linux\n");
 12     //printf("hello linux\n");
 13 
 14     return 0;
 15 }

预处理

头文件展开:本质在预处理的时候,将头文件内容拷贝至源文件
去注释
宏替换
条件编译

gcc -E test.c -o test.i

-E : 从现在开始进行程序的翻译过程,预处理做完的时候就停下来
在这里插入图片描述
上面多出的八百多行代码都是头文件展开

条件编译

条件编译的本质:对代码进行裁剪

  1 #include <stdio.h>
  2 #define VERSION1 1
  3 // #define VERSION2 2
  4                                                                                                                                                                     
  5 int main()
  6 {
  7     printf("hello linux\n");
  8 #ifdef VERSION1 
  9     printf("hello version1.0\n");
 10 #elif VERSION2 
 11     printf("hello version2.0\n");
 12 #else
 13     printf("hello free version\n");
 14 #endif
 15     //printf("hello linux\n");
 16     //printf("hello linux\n");
 17     //printf("hello linux\n");
 18     //printf("hello linux\n");
 19     //printf("hello linux\n");
 20 
 21     return 0;
 22 }

在这里插入图片描述
将test.c里面的两个宏都注释掉,可以在gcc指令里面添加宏 -D

gcc test.c -o test.exe -D VERSION1=1
gcc test.c -o test.exe -DVERSION1=1
//可以连着也可也不连着

在这里插入图片描述

应用场景
1、对于软件的专业版与社区版,维护一份代码,可以用条件编译对里面的功能进行裁剪
2、头文件定义上,防止头文件被重复包含

#ifndef __CODE_H__
#define __CODE_H__
// XXXX
#endif

编译

C -> 汇编
从test.c开始也许, -S 从现在开始进行语言的翻译,当编译工作完成就停止

gcc -S test.i -o test.s

形成汇编语言
在这里插入图片描述

汇编

汇编 -> 二进制,可重定位目标二进制文件(不能执行
test.o : 可重定位目标二进制文件

gcc -c test.s -o test.o

vim是文本编辑器,所有对于二进制展现出来是乱码
在这里插入图片描述

链接

将可执行程序与库关联起来

gcc -o test test.o

ldd 命令可以查询一个可执行文件所依赖的库
在这里插入图片描述
其中/lib64/libc.so.6就是所用的C语言的库

g++

1、编译失败问题
在这里插入图片描述
输入下列指令

sudo yum -y install gcc+ gcc-c++

2、编译形成指定名称的可执行程序
C语言也可以用g++编译,g++的选项与gcc一样
在这里插入图片描述

g++ test.c -o mybincpp
g++ -o mybincpp test.c

动静态库的理解 – 链接

我们所写的代码都是代码+调用的库
库让我们写一份代码不用从零开始
都是文件
在这里插入图片描述

下面这个是个动态库
在这里插入图片描述
去掉lib(所有库都以这个开头),去掉.so.6,所有这个库是个c库
动态库 -> 动态链接
静态库 -> 静态链接

动态库
优点:节省资源,不会出现太多的重复代码 — 资源(磁盘、内存、网络(如果你在一个网站上传一份重复很多的代码,那别人下载也是在浪费资源)等)
缺点:对库的依赖性比较强,一旦库丢失,所以使用这个库的程序都无法运行
静态库
优点:不依赖库,同类型平台中都可以直接运行使用
缺点:可执行程序体积比较大,比较浪费资源 — 资源(磁盘、内存、网络(如果你在一个网站上传一份重复很多的代码,那别人下载也是在浪费资源)等)

动态链接、动态库

被多个使用者共享使用,一旦缺失,所有程序都不可以运行了!!
我们调用哪个库,只是在代码中指明库的地址
在这里插入图片描述

静态链接、静态库

代码中我们用到哪个库,直接硬拷过来,成为静态链接
在这里插入图片描述

ldd

ldd可以查看一个文件库的依赖情况
在这里插入图片描述

file

动态库又称为共享库
在这里插入图片描述
形成用静态库的可执行程序在这里插入图片描述

注意:一般程序是不会给安装静态库de,需要用yum进行安装
ld是连接器
sudo yum install -y glibc-static libstdc++-static在这里插入图片描述
在这里插入图片描述

四、 make/makefile – 项目自动化构建

在linux中是使用命令行的,如果有十几个源文件,难道每一个都要用gcc/g++去进行预处理、编译、汇编等操作吗?

make是一个命令
makefile是一个文件(保存的依赖关系和依赖方法)

快速使用

1、创建Makefile/makefile文件

touch Makefile
touch makefile

在这里插入图片描述

2、vim打开这个文件
第一行:依赖关系
第二行:依赖方法
在这里插入图片描述

在这里插入图片描述

解释依赖关系和依赖方法

依赖关系:我为什么要帮你?
依赖方法:我怎么帮你?
目标文件:依赖文件列表(用空格作为分隔符)
形成可执行文件的方法

清理项目

clean后面为空,需要依赖关系,但依赖关系为空
在这里插入图片描述

make的小知识点

1、Makefile和make形成目标文件的时候,默认是从上到下扫描makefle的文件,默认形成的第一个目标文件
2、默认只形成一个
3、 make和makefile怎么知道可执行程序是比较新的呢??这个是通过对比时间比出来的,只要可执行程序的最近修改时间比所有源文件的最近修改时间新,说明它就是最新的!
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

认识的文件的时间

1、Modify:对文件内容做修改时
2、Change:对文件属性做修改时
3、Accesss:文件访问时间,只有对文件内容进行打印查看的时候才会改变

1、当对文件内容进行修改的时候,文件的大小也会改变,连带着文件的属性也变了
在这里插入图片描述
2、对权限进行修改的时候不会改变内容,因此只有Change改变了
在这里插入图片描述
3、
在这里插入图片描述

Access并不是每一次都会改变:最初设计的时候,每次查看Access都会改变更新。相比于修改内容和属性,查看文件是十分频繁的,这导致Access会频繁更新,进而造成资源浪费。-- 当短时间内频繁查看时,Access只会在第一次时修改,之后不再修改
4、当不想更改文件内容,而想让Modify更新
可以用touch,当创建的文件存在时,它只会刷新文件的时间。
在这里插入图片描述

5、不用touch就make
如果每一次make都要touch一下太麻烦了 — PHONY
修饰mybin目标文件,成为一个伪目标
在这里插入图片描述

在这里插入图片描述

但我们一般是给clean

.PHONY:clean

补充makefile的语法

&@ 、 &^

&@代表mybin
$^代表mytest.c
在这里插入图片描述

makefile里面的全局变量

在这里插入图片描述

关于makefile/make的语法推导

在这里插入图片描述

五、 第一个小程序 – 进度条

写源代码之前,先把makefile写通

预备的两个小知识

缓冲区

有\n时,现在屏幕上显示,再结束程序

#include<stdio.h>
#include<unistd.h>
	int main()
   {
       printf("you can see me\n");
   
       sleep(3);                                                                                                                                                       
       return 0;
  }

在这里插入图片描述

无\n时,整个程序都结束了,再在屏幕上显示

#include<stdio.h>
#include<unistd.h>
	int main()
   {
       printf("you can see me");
   
       sleep(3);                                                                                                                                                       
       return 0;
  }

在这里插入图片描述

回车与换行

回车和换行用于输出时,控制光标的
换行:从上一行到下一行
回车:从光标所在位置回到这一行的最开始
\n:回车+换行
\r:回车

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

但因为没有\n就不会刷新缓冲区 -> 所以程序都结束才会显示 -> 解决方法:fflush(强制刷新)
fflush有三种参数:stdout、stdin、stderro

入门版的进度条

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<string.h>
  4 
  5 #define MAX 101
  6 #define LABLE '='
  7 
  8 int main()
  9 {
 10     char bar[MAX];
 11     memset(bar,'\0',sizeof(bar));
 12                                                                                                                                                                     
 13     int i = 0;
 14     while(i<=100)
 15     {
 16         printf("%s\r",bar);
 17         fflush(stdout);
 18         bar[i++] = LABLE;
 19         usleep(100000);
 20     }
 21     printf("\n");
 22 
 23     return 0;
 24 }

在这里插入图片描述

printf("%s\r", bar)每次打印完之后都回车到最开始再打印
fflush(stdout)因为没有\n所以程序只有在结束的时候才显示,这条程序是强制刷新

升级版进度条 – 设计上

多文件的Makefile

processbar.h:放头文件
processbar.c:放进度条的是实现方法
main.c:调用processbar方法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
多窗口的编辑
(1)在低行模式中 -> : -> vs 文件名
(2)移动光标,在命令行模式ctrl+ww
在这里插入图片描述

version1

在这里插入图片描述
在这里插入图片描述

    1 #include"processbar.h"
    2 #include<string.h>
    3 #include<unistd.h>
    4 
    5 //version 1
    6 void process()
    7 {
    8     char bar[MAX];
    9     memset(bar, '\0', sizeof(bar));
   10     char* x = "/|\\-";
   11     int i = 0;
   12     while(i <= 100)
   13     {
   14         printf("[%-100s]%c[%3d%%]\r", bar, x[i%4], i);                                                                                                            
   15         fflush(stdout);
   16         bar[i++] = s;
   17         usleep(100000);
   18     }
   19 
   20     printf("\n");
   21 }

在这里插入图片描述

问题:在我们具体场景里面,怎么知道具体进度是多少

version2

模拟应用场景
filedown模拟下载场景

    1 #include"processbar.h"
    2 #include<time.h>
    3 #include<stdlib.h>
    4 
    5 #define FILEMAX 1024*1024*1024
    6 
    7 void filedown(callback_t cb)
    8 {
    9     srand(time(NULL)^1023);
   10     int total = FILEMAX;
   11     while(total)
   12     {
   13         total -= rand()%(1024*1024);
   14         if(total<0)
   15             total = 0;
   16         int downtotal = FILEMAX - total;
   17         double rate = ((downtotal*1.0)/(FILEMAX))*100.0;
   18         usleep(10000);
   19         cb(rate);                                                                                                                                                 
   20     }
   21 }
   22 
   23 int main()
   24 {
   25     filedown(process_flush);
   26     return 0;
   27 }
  ~

  1 #include"processbar.h"
  2 #include<string.h>
  3 #include<unistd.h>
  4 
  5 //version 1
  6 void process()
  7 {
  8     char bar[MAX];
  9     memset(bar, '\0', sizeof(bar));
 10     const char* x = "/|\\-";
 11     int i = 0;
 12     while(i <= 100)
 13     {
 14         printf("[%-100s]%c[%3d%%]\r", bar, x[i%4], i);
 15         fflush(stdout);
 16         bar[i++] = s;
 17         usleep(100000);
 18     }
 19 
 20     printf("\n");
 21 }
 22                                                                                                           
 23 //version2                                                                                                   
 24                                                                                                                                
 25 char bar[MAX] = {0};                                                                                                                           
 26 const char* x = "/|\\-";                                                                                     
 27 void process_flush(double rate)                                                 
 28 {                                                                                           
 29     int i = rate;                                                                                                                                                   
 30     if(rate < 1.0)                                                                     
 31         bar[0] = head;
 32     printf("[%-100s]%c[%.1f%%]\r", bar, x[i%4], rate);                                  
 33     fflush(stdout);                                                                                                
 34     bar[i++] = body;
  35     if(i < 100)
 36         bar[i] = head;
 37     if(rate >= 100.0)
 38         printf("\n");
 39 }

  1 #pragma once 
  2 
  3 #include<stdio.h>
  4 
  5 #define MAX 101
  6 #define body '='
  7 #define head '>'
  8 #define s '#'
  9 typedef void(*callback_t)(double);
 10                                                                                                                                                                     
 11 //version 1
 12 void process();
 13 void process_flush(double rate);

在这里插入图片描述
在这里插入图片描述

此时光标的旋转受下载量的影响,修改使它独立显示

   22 //version2                                                                                                   
   23                                                                                                              
   24 char bar[MAX] = {0};
   25 const char* x = "/|\\-";
   26 void process_flush(double rate)
   27 {                              
   28     static n = 0;
   29     int i = rate;      
   30     if(rate < 1.0)                                                                                                                                                                                                                                                                                                                          
   31         bar[0] = head;
   32     printf("[%-100s]%c[%.1f%%]\r", bar, x[n%4], rate);
   33     fflush(stdout);                                   
   34     n++;                                                                                                                                                          
   35     bar[i++] = body;
   36     if(i < 100)     
   37         bar[i] = head;
   38     if(rate >= 100.0) 
   39         printf("\n");
   40 }

还可以有颜色

补充

rand随机数

rand()函数:
1.C语言中用来产生随机数
2.需要的头文件:stdlib.h
3.stdlib.h头文件中有宏#define RAND_MAX 0x7fff,会返回一个范围0-0x7fff的随机数,即最大是32767的一个数
4.rand()函数得原型

#include <stdlib.h>

int rand(void);

5.rand函数的调用

rand()函数每次调用前都会查询是否调用过srand(seed),是否给seed设定了一个值,如果有那么它会自动调用srand(seed)一次来初始化它的起始值。若之前没有调用srand(seed),那么系统会自动给seed赋初始值,即srand(1)自动调用他一次。(在调用rand()函数之前,可以使用srand()函数设置随机数种子,如果没有设置随机数种子,rand()函数在调用时,自动设计随机数种子为1。随机种子相同,每次产生的随机数也会相同)

time

为了使每次产生的随机数不同,可以使用time来做随机种子

time_t time(time_t *t);

函数说明:此函数会返回从公元1970年1月1日的UTC时间从0时0分0秒算起到现在所经过的秒数(即格林尼治时间1970年1月1日00:00:00到当前时刻的时长,时长单位是秒)。如果t并非空指针的话,此函数也会将返回值存在t指针所指的内存。

#include<time.h>

在这里插入图片描述

  • 10
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值