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

【寻找Linux的奥秘】第四章:基础开发工具(下)

1

请君浏览

    • 前言
    • 1. 自动化构建
      • 1.1 背景
      • 1.2 基本语法
      • 1.3 make的运行原理
      • 1.4通用的makefile
    • 2. 牛刀小试--Linux第一个小程序
      • 2.1 回车与换行
      • 2.2 行缓冲区
      • 2.3 倒计时小程序
      • 2.4 进度条小程序
        • 原理
        • 代码
    • 3. 版本控制器git
      • 3.1 认识
      • 3.2 git的使用
        • 三板斧
      • 3.3 其他
    • 4. 调试器gdb/cgdb
      • 4.1 了解
      • 4.2 使用
      • 4.3 小技巧
        • 4.3.1 安装cgdb
        • 4.3.2 watch
        • 4.3.3 set var
        • 4.3.4 条件断点
    • 尾声

前言

本专题将介绍关于Linux操作系统的种种,那么上一章我们讲解了Linux中最常用的编辑器vim和编译器gcc,本章将继续讲解Linux中的其他的基本开发工具。(本章节默认使用的环境是centos 7.8)

1. 自动化构建

1.1 背景

首先,我们要知道什么是自动化构建,自动化构建到底有什么作用。

自动化构建是提高开发流程效率与质量的工具。在Linux中最常用的自动化构建工具由两部分组成:make和makefile

  • make是⼀个命令⼯具,用于解释makefile中指令的命令⼯具QQ20250406-000404
  • makefile是一个文件,用于定义构建规则和依赖关系

两者搭配使用,完成项目自动化构建。

那么自动化构建适用于哪里、有什么作用呢?

在我们编写一些项目时,通常会把各种声明和定义以及测试放在不同的文件中,例如我们之前自己实现数据结构的时候:

QQ20250408-193019

我们会把栈的各种声明放在Stack.h的头文件中,把其中函数的具体实现放在Stack.c中,最后在main.c中进行测试以及使用,放在不同的文件中可以提高代码的可维护性以及方便代码的复用等好处,特别是在大型项目这些好处体现的就会更加明显。

我们知道,对于这种多文件的编译我们是先把所有的.c文件编译为.o文件,也就是可重定位目标二进制文件,使之停留在汇编阶段,然后再将所有.o文件链接形成最后的可执行文件。那么在Linux下我们该如何操作呢?其实很简单,如下图所示:

QQ20250408-194832

QQ20250408-194745

我们只需要用gcc同时编译需要链接的.c文件,这样它们就可以链接在一起了。虽然目前来看也并没有难度,可是如果我们需要链接的一起的源文件有几十个、几百个、甚至上千个呢?如果再靠我们一个一个手动去输入的话恐怕等输入完黄花菜都凉了。这个时候就需要用到我们的自动化构建工具——make了。我们可以通过一个make命令来完成这繁琐以及更复杂的功能。

⼀个⼯程中的源⽂件不计数,其按类型、功能、模块分别放在若⼲个⽬录中,我们可以在makefile文件中定义⼀系列的规则来指定,哪些⽂件需要先编译,哪些⽂件需要后编译,哪些⽂件需要重新编译,甚⾄于进⾏更复杂的功能操作。通过make软件来执行我们makefile文件中的操作,可以实现大面积的自动化。

makefile带来的好处就是⸺“⾃动化编译”,⼀旦写好,只需要⼀个make命令,整个⼯程完全⾃动编译,极⼤的提⾼了软件开发的效率。

下面让我们来看看该如何使用make。

1.2 基本语法

使用make最重要的就是编写makefile文件了,只有在makefile文件中合理且正确的写出我们需要的指令,才能使用make来达到我们想要的效果,下面让我们简单来看一看如何在makefile中编写指令从而可以编译我们上面的代码:

我们先来看一个最简单但没有通用性的:

QQ20250409-145547

例如上图,test.c是一个我们最基础的C语言代码,我们通过编写Makefile文件执行make命令,就可以自动编译该文件:

QQ20250409-145740

下面让我们来看一看Makefile文件中的每一句指令都是什么意思,代表了什么:

QQ20250409-151248

  • 目标文件:首先目标文件也就是我们通过依赖关系和依赖方法需要形成的文件
  • 依赖关系:依赖关系是我们生成目标文件所需要的文件
  • 依赖方法:依赖方法是我们通过依赖关系生成目标文件的命令
  • 伪目标:在Makefile中,伪目标是一种特殊的目标,它们不对应于实际的文件,而是用来执行特定的命令。伪目标通常用于清理项目(如删除编译生成的文件),执行测试,或者其他不产生文件的操作。

1.3 make的运行原理

clean这种,没有被第⼀个⽬标⽂件直接或间接关联,那么它后⾯所定义的命令将不会被⾃动执⾏,不过,我们可以显⽰要make执⾏。即命令⸺make clean,以此来清除所有的⽬标⽂件,以便重编译。因此,我们通常将它设置为伪目标。用.PHONY 修饰,伪⽬标的特性是,总是被执⾏的。

QQ20250409-153917

总是可执行我们该如何理解呢?想要理解这个概念我们要知道make是如何⼯作的,在默认的⽅式下,也就是我们只输⼊make命令。那么:

  • 首先,make会在当前⽬录下找名字叫Makefilemakefile的⽂件,在找到Makefile文件后会自定向下扫描Makefile文件,默认形成第一个目标文件,如果想要指定形成,可以使用make+targetname命令。还是以上面的Makefile为例,它会找到test这个文件,并把这个文件作为最终的目标文件。

我们修改一下Makefile中的内容,来演示一下在Makefile中如果依赖关系暂时不存在时make的运行:

QQ20250409-214801

如上图所示,使用make默认形成的最终文件是test,它的依赖是test.o,可是我们在当前目录下并没有找到test.o文件,那么那么 make 会寻找⽬标为test.o ⽂件的依赖性,如果找到则再根据那⼀个规则⽣成tesc.o ⽂件。(这有点像⼀个堆栈的过程),具体的过程如下图所示:

QQ20250409-221036

这就是整个make的依赖性,make会⼀层⼜⼀层地去找⽂件的依赖关系,直到最终编译出第⼀个⽬标⽂件。在找寻的过程中,如果出现错误,⽐如最后被依赖的⽂件找不到,那么make就会直接退出,并报错。make只管⽂件的依赖性,即,如果在我找到了依赖关系之后,冒号后⾯的⽂件还是不存在,那么就会报错。

那么如果我们连续使用make命令会发生什么呢?

我们拿上面的Makefile为例,如果test文件不存在,或者 test 所依赖的后⾯的 test.c ⽂件的⽂件修改时间要⽐ test 这个⽂件新,那么,他就会执⾏后⾯所定义的命令也就是依赖方法来⽣成test 这个⽂件。 但是当test存在且它所依赖的test.c文件的修改时间要小于test的修改时间,那么我们再次执行make命令时系统会给我们一个提示,并且make不再执行:

QQ20250409-184533

如上图所示,我们在使用一次make后再次使用系统给了我们一个提示:test文件以及是最新的了。如果再次进行编译得到的结果也与之前一样。那么make是怎么识别的呢?它其实看的就是test文件与test.c文件修改时间的比较,test.c的修改时间小于test:

QQ20250409-185443

那么什么是修改时间呢?这里就涉及到了文件属性中的三大时间,分别为:

  • 访问时间(atime):最近一次访问的时间,使用cat、more等指令时该时间会改变。
  • 修改时间(mtime):文件内容最后被修改的时间,对文件进行写入操作并保存后该时间会改变。
  • 状态改动时间(ctime):文件属性最后被修改的时间,文件的属性包括大小、权限等等,当它们发生变化的时候该时间会改变。

QQ20250409-190120

(小贴士:我们可以用stat命令查看文件的详细属性,用file命令查看文件的详细类型)

其中,make比较的是文件的修改时间(mtime),也就是Modify时间,通过下图相信大家能有更深的理解:

QQ20250409-191838

上面的原理我们理解之后再来看伪目标的总是被执行的特性就可以理解了,也就是说伪目标可以让make忽略源⽂件和可执⾏⽬标⽂件的M时间对⽐,每次使用时都可以被执行。

1.4通用的makefile

上面我们所写的makefile局限性很大,它限制了我们源文件的文件名以及个数,那么我们该如何实现一个通用的makefile文件呢?

  • 首先,对于很多的程序它的源文件都不止一个,我们需要先将这些源文件都编译成.o文件,然后再进行链接形成可执行程序。

我们通过下图来介绍一下,这就是一个比较通用的Makefile文件:

QQ20250409-224309

  • 在Makefile文件中#用来注释,使用变量需要用$(变量名)
  • 在命令前加上@符号可以在make执行时不在shell上再显示执行的命令,也就是使命令不再回显
  • 我们用echo可以显示我们使用make的过程
  • $^代表依赖文件列表,$@代表目标文件名,$<代表对展开的依赖.c文件,一个个交给gcc
  • %.c:展开当前目录下所有的.c文件
  • %.o:展开当前目录下所有的.o文件

下面让我们来看一看效果,我们用最开始的代码为例:
QQ20250409-225208

当前我们只有两个源文件,已经能够管中窥豹,如果是在大型项目中,使用自动化构建make会非常的方便。当然,上面的通用Makefile文件也只是一个简单的版本,我们还可以加入更多的指令去满足我们更多样化的需求,在使用中相信大家会逐渐体会到make对于提高编译效率方面的好处。

2. 牛刀小试–Linux第一个小程序

工具学到这里,我们已经学会了编辑器vim、编译器gcc和自动化构建make,这些已经可以支撑我们在Linux中写一些有趣的小程序了。俗话说得好,光说不练假把式。既然我们已经学了这么多工具,那么接下来让我们来实际的上手操作一下,巩固之前的学习,让我们来一个小程序叫做进度条。

2.1 回车与换行

在写进度条之前我们需要先明确两个概念:回车与换行。我们日常经常把回车和换行看作是同一种东西,其实并不然:

  • 回车:回到所在行的起始位置
  • 换行:换到当前位置的下一行

如下图所示:QQ20250409-230518

可以看到,我们实际上的换行操作是换行加上回车,我们的'\n'就是一个典型的例子,键盘上的Enter键的图标也在提醒我们:

QQ20250409-231104

在C语言中,我们用'\r'来表示回车。

2.2 行缓冲区

接着我们再来看一看行缓冲区的概念。这里提出一个问题:我们使用printf函数打印的内容是直接出现在显示器上的吗?

我们可以通过代码来验证一下:

QQ20250409-231911

通过对两种情况的测试我们发现,在带\n时,我们打印的内容是先出现在显示屏后再等待两秒;而不带\n时,是先等待了两秒后我们打印的内容才显示在显示器上。

这是因为在内存上存在一片缓冲区,我们显示器的刷新策略是行刷新:一行一行的刷新。在遇到'\n'时由于要进行换行,所以直接刷新在显示器上,而没有\n时,要打印的内容一直在缓冲区中,当程序运行完后才刷新到显示器上。那么有没有什么方法让它立即刷新呢?C语言提供了一个名为fflush的函数,可以立即刷新缓冲区中的内容:

QQ20250409-232658

那么在使用fflush函数后我们可以发现,即便没有'\n',我们的程序也是先打印出内容后再进行等待:

QQ20250409-232923

2.3 倒计时小程序

那么基于此,我们便可以写一个简单的倒计时程序:

#include<stdio.h>
#include<unistd.h>
int main()
{int ret = 10;while(ret >= 0){printf("%-2d\r", ret--);fflush(stdout);sleep(1);}printf("\n");return 0;
}

每一次打印后’\r’回到起始位置,然后使用fflush函数将缓冲区中的内容刷出,每次打印间隔一秒,这样,我们就得到了一个简单的倒计时程序。

2.4 进度条小程序

上面通过简单的倒计时小程序我们学会了'\r'结合fflush的小用法,那么接下来让我们更进一步,在设计一个进度条程序。

原理

我们再下载程序以及上传软件等状况下都会有一个进度条来显示我们的进度。一个简单的进度条我们可以看作三个部分组成:条形图、百分比、旋转光标

QQ20250409-234113

我们知道,在进度条运行的过程中总长度并不会改变,只是条形图中的填充物会逐渐增多,百分比逐渐变大,旋转光标不停的转动,代码进度条在正常运行。因此,我们只需要提前预留出若干个空间,用作填充条形图,预留空间是固定条形图的总长度;然后根据倒计时小程序去设计百分比不断的变大,直到达到百分之百;而旋转光标我们只需要用一个字符数组,不断遍历其中的字符即可。

代码

思路有了,那么让我们直接用vim来编写我们在Linux中的C语言程序吧:

#include "process.h"
#include <string.h>
#include <unistd.h>#define NUM 101
#define STYLE '='int main()
{char buffer[NUM];memset(buffer, 0, sizeof(buffer));const char *lable="|/-\\";int len = strlen(lable);int cnt = 0;while(cnt <= 100){printf("[%-100s][%d%%][%c] \r", buffer, cnt, lable[cnt%len]);fflush(stdout);buffer[cnt]= STYLE;cnt++;usleep(50000);} printf("\n");
}

QQ20250409-235700

运行后我们可以发现跟我们的预期基本一致。当然,我们这个只是非常简易的进度条,并没有什么实际用途,我们只是用作对之前所学工具的巩固。大家感兴趣的话也可以自己去模拟变化的网速去设计更加有效果的进度条玩一玩。

3. 版本控制器git

3.1 认识

我们该如何理解版本控制呢?这里举一些简单的例子:

  • 当我们再玩一些单机的游戏时,由于我们的各种游戏数据都存储在本地,因此当我们在打boss前或者去进行一些危险的操作时可以提前把我们的游戏数据进行备份,这样在我们打boss失败了还损失了强力道具时我们可以通过之前的备份来恢复到我们打boss前的状态。当然我们可以在不同的时间段留下不同的备份,可以使我们恢复到想要的时间段。

  • 我们写论文的时候也是如此,当我们写完初稿后会找导师进行请教,根据导师的建议不断完善我们的论文,每一次修改前我们都需要做好相应的备份,以便失误后能够恢复到原来的版本。

这些不同的备份我们通常将其称作不同的版本,当我们的版本越来越多之后,我们该如何知道每个版本各自都是修改了什么呢?

我们写的项目代码也是如此,随着不断的迭代产生了许多不同的版本。为了方便管理这些不同版本的文件,便有了版本控制器

所谓的版本控制器,就是能让你了解到⼀个⽂件的历史,以及它的发展过程的系统。通俗的讲就是⼀个可以记录⼯程的每⼀次改动和版本迭代的⼀个管理系统,同时也⽅便多⼈协同作业

⽬前最主流的版本控制器就是 Git 。Git 可以控制电脑上所有格式的⽂件,例如 doc、excel、dwg、dgn、rvt等等。对于我们开发⼈员来说,Git 最重要的就是可以帮助我们管理软件开发项⽬中的源代码⽂件!⾃诞⽣于 2005 年以来,Git ⽇臻成熟完善,在⾼度易⽤的同时,仍然保留着初期设定的⽬标。 它的速度⻜快,极其适合管理⼤项⽬,有着令⼈难以置信的⾮线性分⽀管理系统。

但是这些文件只是放在本地可能会遭遇硬件受损等外力影响导致文件丢失,于是,基于Git的代码托管服务平台就诞生了,例如我们耳熟能详的Github,这是一个全球程序员都在使用的代码托管平台。但是由于某些原因,我们在国内想要使用GitHub不太容易。但是国内也有自己的代码托管平台,例如Gitee

QQ20250411-171742

3.2 git的使用

我们要想使自己的项目上传到远端,也就是GitHub或者Gitee上,首先需要有相应平台的账户(由于某些原因,我们以Gitee为例),然后新建一个仓库:

QQ20250411-172402

然后根据我们的需要填写相关的内容:

QQ20250411-172421

创建好之后我们点击克隆/下载,复制对应的链接 :

QQ20250411-172747

之后我们在Linux下就可以下载项目到本地了(windows的操作一样):git clone [url],url就是我们刚才复制的链接。

QQ20250411-174706

当然,如果你在GitHub和Gitee上想要下载开源项目也是一样的操作,复制项目的链接使用上面的命令下载到本地。

我们可以先检查一下当前环境下是否安装了git,通过命令git --version

如果没有安装,我们使用命令yum install -y git进行安装。

我们来看一下下载到本地后都有些什么文件:

QQ20250411-174909

  • 前两个不用再进行解释了,分别代表了上级目录和当前目录
  • README.md:可以理解为项目说明书,一份中文版,一份英文版。
  • .git:本地仓库。里面包含了我们所有的修改记录。
  • .gitignore:在该文件中进行配置可以忽略一些特殊不需要或者不想add的文件。

Git提交的时候,只会提交变化的部分。例如我们有一个100行代码的文件,我们对其最后一行进行了修改,随后提交到了git上,这里git上只是保存了我们变化的那一部分,而不是全部保存。

三板斧
  1. git add

    将文件放到刚才下载好的目录中

    git add [文件名]

    第一步将需要用git管理的文件告知git。

  2. git commit

    提交改动到本地

    git commit -m "说明"

    提交的时候应该注明提交⽇志, 描述改动的详细内容。

  3. git push

    同步到远端服务器上

    git push

    需要填⼊⽤⼾名和密码,同步成功后, 刷新 Gitee⻚⾯就能看到代码改动了。

我们来操作一下:

我们在拉取项目到本地后的目录称为工作区,我们在工作区中新建一个文件:

QQ20250411-180920

这个时候我们的code文件还不在本地仓库中,我们需要把他先add到一块命为暂存区的地方,然后commit把暂存区中的所有内容提交到本地仓库,最后在push同步到远端仓库上:

QQ20250411-182520

(我们可以使用git add *将当前目录下所有陌生的文件添加到暂存区中)

push我们需要输入账户名和密码:

QQ20250411-183132

成功之后刷新我们的Gitee网页,就可以看到代码已经同步了:

QQ20250411-183213

3.3 其他

我们可以使用git log 来查看我们该仓库所有的提交记录:

QQ20250411-183811

使用git进行版本管理,我们只进行管理源文件,也就是.c .cpp .h等,不管理各种临时文件,上面我们提到的.gitignore文件中就是各种临时文件的后缀名,可以帮助我们过滤这些文件,在提交的时候不提交这些文件:

QQ20250411-184831

当然,我们也可以进行修改,例如加入一些我们不需要的特殊文件。

git status 命令是一个用于查看 Git 仓库当前状态的命令。它显示了工作目录和暂存区的状态,帮助开发者了解哪些文件已修改、哪些文件未跟踪以及哪些文件已暂存。

至于git还有更多的操作,这里就不再详细的讲解了,我们现在的目的是能够简单的使用git上传和下载项目就可以了。

4. 调试器gdb/cgdb

4.1 了解

相信之前使用vs2022这些集成式开发环境时大家都领略到了调试的魅力,通过调试我们可以快速的找到代码中的问题所在。那么在Linux下我们可以对代码进行调试吗?答案是当然可以。

在Linux下有专门的调试器gdb来帮助我们进行调试的工作。

程序的发布方式有两种,一种是debug模式,一种是release模式,在vs2022上我们想要对代码进行调试需要在debug模式上,在Linux中的gdb也是如此,而我们在Linux下使用gcc/g++进行编译出来的程序默认是release模式,因此要想使用gdb进行调试,我们需要在编译时带上-g选项gcc xxx.c -o xxx -g,使其以debug模式发布。我们日常使用的各种软件都是release模式。

QQ20250413-104426

可以看到我们debug模式下的可执行程序的内存是要大于release模式下的,这是因为在debug模式中包含了我们的调试信息,正是有了这些调试信息我们才能对其进行调试。

两种模式下运行结果也是一样的:

QQ20250413-102756

我们调试的对象是携带调试信息的可执行程序(也就是debug模式),而不是我们的源文件。

4.2 使用

  • 开始:我们直接用gdb加上需要调试的程序名即可使用gdb:gdb [name]

  • 退出:ctrl+d或者quit调试命令

    QQ20250413-111519

下面是一些gdb的常用命令:

命令作⽤样例
list/l显⽰源代码,从上次位置开始,每次列出10⾏list/l 10
list/l 函数名列出指定函数的源代码list/l main
list/l ⽂件名:⾏号列出指定⽂件的源代码list/l mycmd.c:1
r/run从程序开始连续执⾏run
n/next单步执⾏,不进⼊函数内部next
s/step单步执⾏,进⼊函数内部step
break/b [⽂件名:]⾏号在指定⾏号设置断点break 10break test.c:10
break/b 函数名在函数开头设置断点break main
info break/b查看当前所有断点的信息info break
finish执⾏到当前函数返回,然后停⽌finish
print/p 表达式打印表达式的值print start+end
p 变量打印指定变量的值p x
set var 变量=值修改变量的值set var i=10
continue/c从当前位置开始连续执⾏程序continue
删除所有断点delete breakpoints
删除序号为n的断点delete breakpoints 1
disable breakpoints/[断点编号]禁⽤所有/指定断点disable breakpoints
enable breakpoints/[断点编号]启⽤所有/指定断点enable breakpoints
info/i breakpoints查看当前设置的断点列表info breakpoints
display 变量名跟踪显⽰指定变量的值(每次停⽌时)display x
undisplay 编号取消对指定编号的变量的跟踪显⽰undisplay 1
until X⾏号执⾏到指定⾏号until 20
backtrace/bt查看当前执⾏栈的各级函数调⽤及参数backtrace
info/i locals查看当前栈帧的局部变量值info locals
quit退出GDB调试器quit

调试的本质:帮助我们找到代码的问题所在。

4.3 小技巧

在没有图形化界面进行调试还是很难操作的,下面的一些技巧可以帮助我们更好的进行调试。

4.3.1 安装cgdb

我们用gdb的时候只能通过list命令看到我们的代码,不是很方便,cgdb这个工具的命令与gdb基本一样,不过它可以使我们的代码在上方展现,使我们的调试过程更加清晰一点:

QQ20250413-114739

  • Ubuntusudo apt-get install -y cgdb
  • Centossudo yum install -y cgdb
4.3.2 watch

执⾏时监视⼀个表达式(如变量)的值。如果监视的表达式在程序运⾏期间的值发⽣变化,gdb会暂停程序的执⾏,并通知使⽤者:

QQ20250413-141054

如果你有⼀些变量不应该修改,但是你怀疑它修改导致了问题,你可以watch它,如果变化了,就会通知你。

4.3.3 set var

可以直接修改变量的值,可以帮助我们直接确定原因所在:set var [变量名]=[值]

QQ20250413-141502

4.3.4 条件断点

我们在建立断点时可以给予其特定的条件,使其在满足条件时才可以触发:b [行号] [条件]

QQ20250413-141802

当然,我们也可以给已经存在的断点设定条件,使用命令:condition [断点编号] [条件]

QQ20250413-142218

注意:

  • 上面条件断点添加两种⽅式语法略有不同,第一种条件前需要加if,第二种则不用。
  • cgdb中可以使用esc进入上方代码屏,用i回退到下方gdb屏。

尾声

本章讲解就到此结束了,若有纰漏或不足之处欢迎大家在评论区留言或者私信,同时也欢迎各位一起探讨学习。感谢您的观看!

相关文章:

【寻找Linux的奥秘】第四章:基础开发工具(下)

请君浏览 前言1. 自动化构建1.1 背景1.2 基本语法1.3 make的运行原理1.4通用的makefile 2. 牛刀小试--Linux第一个小程序2.1 回车与换行2.2 行缓冲区2.3 倒计时小程序2.4 进度条小程序原理代码 3. 版本控制器git3.1 认识3.2 git的使用三板斧 3.3 其他 4. 调试器gdb/cgdb4.1 了解…...

RK3588上Linux系统编译C/C++ Demo时出现BUG:The C/CXX compiler identification is unknown

BUG的解决思路 BUG描述&#xff1a;解决方法&#xff1a;首先最重要的一步&#xff1a;第二步&#xff1a;正确设置gcc和g的路径方法一&#xff1a;使用本地系统中安装的 aarch64-linux-gnu-gcc 和 aarch64-linux-gnu-g方法二&#xff1a;下载使用官方指定的交叉编译工具方法三…...

记录一次/usr/bin/ld: 找不到 -lOpenSSL::SSL

1、cmake 报错内容如下&#xff1a; /usr/bin/ld: 找不到 -lOpenSSL::SSL /usr/bin/ld: 找不到 -lOpenSSL::Crypto2、一开始以为库没有正确安装 sudo yum install openssl-devel然后查看openssl 结果还是报错&#xff01; 3、尝试卸载安装都不管用&#xff0c;网上搜了好多…...

[16届蓝桥杯 2025 c++省 B] 水质检测

思路&#xff1a;分类讨论&#xff0c;从左到右枚举&#xff0c;判断当前的河床和下一个河床的距离是第一行更近还是第二行更近还是都一样近&#xff0c;分成三类编写代码即可 #include<iostream> using namespace std; int main(){string s1,s2;cin>>s1>>…...

基于PySide6与pycatia的CATIA绘图比例智能调节工具开发全解析

引言&#xff1a;工程图纸自动化处理的技术革新 在机械设计领域&#xff0c;CATIA图纸的比例调整是高频且重复性极强的操作。传统手动调整方式效率低下且易出错。本文基于PySide6pycatia技术栈&#xff0c;提出一种支持智能比例匹配、实时视图控制、异常自处理的图纸批处理方案…...

四、Appium Inspector

一、介绍 Appium Inspector 是一个用于移动应用自动化测试的图形化工具&#xff0c;主要用于检查和交互应用的 UI 元素&#xff0c;帮助生成和调试自动化测试脚本。类似于浏览器的F12(开发者工具),Appium Inspector 的主要作用包括&#xff1a;‌ 1.‌检查 UI 元素‌ …...

玩转Docker | 使用Docker部署MicroBin粘贴板

玩转Docker | 使用Docker部署MicroBin粘贴板 前言一、MicroBin介绍MicroBin 简介主要特点二、系统要求环境要求环境检查Docker版本检查检查操作系统版本三、部署MicroBin服务下载镜像创建容器检查容器状态检查服务端口安全设置四、访问MicroBin服务访问MicroBin首页登录管理后台…...

BGP分解实验·23——BGP选路原则之路由器标识

在选路原则需要用到Router-ID做选路决策时&#xff0c;其对等体Router-ID较小的路由将被优选&#xff1b;其中&#xff0c;当路由被反射时&#xff0c;包含起源器ID属性时&#xff0c;该属性将代替router-id做比较。 实验拓扑如下&#xff1a; 实验通过调整路由器R1和R2的rout…...

MQTT:单片机中MQTTClient-C移植定时器功能

接下来我们完善MQTTTimer.c和MQTTTimer.h两个功能 MQTTTimer.h void TimerInit(Timer* timer); 功能&#xff1a;此函数用于对 Timer 结构体进行初始化。在 MQTT 客户端里&#xff0c;定时器被用于追踪各种操作的时间&#xff0c;像连接超时、心跳包发送间隔等。初始化操作会…...

可拖动的关系图谱原型案例

关系图谱是一种以图结构形式组织和呈现实体间复杂关联关系的可视化数据模型。它通过节点和线构建多维度网络&#xff0c;能直观揭示隐藏的群体特征和传播路径。在社交网络分析、智能推荐系统、知识图谱构建等领域广泛应用。 软件版本&#xff1a;Axure RP 9 作品类型&#xf…...

CST1016.基于Spring Boot+Vue高校竞赛管理系统

计算机/JAVA毕业设计 【CST1016.基于Spring BootVue高校竞赛管理系统】 【项目介绍】 高校竞赛管理系统&#xff0c;基于 DeepSeek Spring AI Spring Boot Vue 实现&#xff0c;功能丰富、界面精美 【业务模块】 系统共有两类用户&#xff0c;分别是学生用户和管理员用户&a…...

从三次方程到复平面:复数概念的奇妙演进(二)

注&#xff1a;本文为 “复数 | 历史 / 演进” 相关文章合辑。 因 csdn 篇幅限制分篇连载&#xff0c;此为第二篇。 生料&#xff0c;不同的文章不同的点。 机翻&#xff0c;未校。 History of Complex Numbers 复数的历史 The problem of complex numbers dates back to …...

PCL 点云投影至指定平面

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 之前的文章中介绍过一个点在平面上的投影坐标,其主要的思路就是利用投影垂线与平面法向量平行的特性,通过推导出的投影公式可以很容易的计算出在某点在某一平面内的投影点。因此只需要重复该过程就可以将整个点云…...

批量将文件名称、文件路径、文件扩展名提取到 Excel 清单

在数字化时代&#xff0c;文件的高效管理至关重要。当我们想要对磁盘中的文件进行整理&#xff0c;想要获取多个文件夹中的文件和路径信息&#xff0c;就需要现将这些文件的名称及路径信息提取出来。本文将介绍一种实用的批量提取技术&#xff0c;帮助用户优化文件管理流程&…...

KWDB创作者计划—KWDB场景创新:多模态数据融合与边缘智能的产业实践

引言&#xff1a;AIoT时代的数据基座重构 在工业物联网设备数量突破千亿、边缘计算节点覆盖率达75%的2025年&#xff0c;传统数据库面临多模态数据处理效率低下、边缘端算力利用率不足、跨域数据协同困难等核心挑战。KWDB&#xff08;KaiwuDB Community Edition&#xff09;通过…...

计算机系统概论

1. 计算机系统的基本组成 计算机系统由 硬件系统 和 软件系统 两大部分协同工作&#xff1a; 硬件系统&#xff1a; 基于冯诺依曼体系结构&#xff08;存储程序原理&#xff09;&#xff0c;包含五大核心部件&#xff1a; 运算器&#xff08;ALU&#xff09;&#xff1a;执行算…...

Android Cmake构建的项目,需不需要配置指定ndk及版本

在 CMake 构建的 Android 项目中&#xff0c;是否需要显式配置 NDK 及其版本&#xff0c;取决于项目的具体需求和环境。以下是详细分析和建议&#xff1a; 1. 是否需要显式配置 NDK 及版本&#xff1f; 情况 1&#xff1a;Android Studio 自动管理 NDK&#xff08;推荐&#x…...

国内AI大模型卷到什么程度了?

目录 1.开源大模型更有前景吗&#xff1f; 2.参数越大真的越牛逼吗&#xff1f; 3.榜单排名有意义吗&#xff1f; 大家好这里是AIWritePaper官方账号&#xff0c;官网&#x1f449;AIWritePaper~ 大模型开源更有前景&#xff1f; 参数越大真的越牛逼吗&#xff1f; 榜单排…...

【HDFS入门】Hadoop 2.0+ HDFS核心架构深度解析:高可用设计揭秘

目录 1 HDFS核心架构概述 2 高可用设计背景 3HDFS核心组件 3.1 Active与Standby NameNode 3.2 JournalNode 3.3 ZKFailoverController&#xff08;ZKFC&#xff09; 3.4 DataNode 4 高可用设计的工作流程 写入阶段&#xff1a; 元数据同步&#xff1a; 健康监测&…...

RabbitMQ安装

RabbitMQ安装 Ubuntu环境安装 一、安装Erlang #更新软件包 sudo apt-get update #安装erlang sudo apt-get install erlang 二、安装RabbitMQ #更新软件包 sudo apt-get update #安装rabbitmq sudo apt-get install rabbitmq-server #确认安装结果 systemctl status rabbitmq-…...

2022 CCPC Henan Provincial Collegiate Programming Contest K 复合函数

补题链接 看网上题解很少&#xff0c;来写一份&#xff0c;这题个人觉得思维难度不是特别大&#xff0c;难度主要在于代码准确度,首先将问题转化成 x x x 向 f ( x ) f(x) f(x) 连边&#xff0c;这一步转化应该是比较容易想到的&#xff0c;通过手模样例&#xff0c;会有类…...

Linux : 多线程互斥

目录 一 前言 二 线程互斥 三 Mutex互斥量 1. 定义一个锁&#xff08;造锁&#xff09; 2. 初始化锁 3. 上锁 4. 解锁 5. 摧毁锁 四 锁的使用 五 锁的宏初始化 六 锁的原理 1.如何看待锁&#xff1f; 2. 如何理解加锁和解锁的本质 七 c封装互斥锁 八 可重入…...

【数学建模】佳点集(Good Point Set)在智能优化算法中的应用与实现

佳点集(Good Point Set)在智能优化算法中的应用与实现 文章目录 佳点集(Good Point Set)在智能优化算法中的应用与实现1. 佳点集概述2. 佳点集的数学原理3. 佳点集在智能优化算法中的应用3.1 改进麻雀搜索算法(SSA)3.2 改进量子粒子群优化算法(QPSO)3.3 自适应分组差分变异狼群…...

redis linux 安装简单教程(redis 3.0.4)

redis.3.0.4.tar.gz 下载地址 链接: https://pan.baidu.com/s/19VAcrA6XS4mIesH6e5Jftg 提取码: bn2r &#xff08;1&#xff09;以安装目录&#xff1a;/home/zsl &#xff08;2&#xff09;将redis-3.0.4.tar.gz 拷贝到/home/zsl &#xff08;3&#xff09;tar xzvf redis-3.…...

探秘 Python 网络编程:构建简单聊天服务器

在计算机网络的世界里&#xff0c;网络编程是实现不同设备之间通信的关键技术。Python 凭借其简洁的语法和强大的库支持&#xff0c;在网络编程领域有着广泛的应用。无论是构建简单的聊天服务器&#xff0c;还是开发复杂的网络应用&#xff0c;Python 都能轻松胜任。 1 理论基础…...

debian转移根目录

如何在 BIOS 启动的 Debian 虚拟机中将根目录转移到 /dev/sda 设备上&#xff1f;本文将从硬盘分区&#xff0c;根目录复制&#xff0c;重新启动等几个方面介绍。 硬盘分区 1.检查磁盘&#xff1a;查看当前的磁盘和分区情况&#xff0c;确认新添加的磁盘设备名称。 parted -…...

vue3 element-plus表单验证

第一准备一个表单 form.vue <template><div><el-form><el-form-item label"姓名" prop"name"><el-input v-model"data.name" placeholder"请输入姓名"></el-input></el-form-item></e…...

Deepseek IP-Adapter与InstantID的区别

IP-Adapter与InstantID均为基于扩散模型的图像生成控制技术&#xff0c;但两者的算法设计目标、核心模块及应用场景存在显著差异。以下从技术架构、特征处理、条件控制等维度对比两者的差异&#xff1a; 1. 核心设计目标 IP-Adapter 由腾讯团队提出&#xff08;2023年8月&…...

OSI 七层模型与 TCP/IP 协议栈详解

OSI 七层模型与 TCP/IP 协议栈详解 网络协议模型是理解计算机网络和通信的基础&#xff0c;而 OSI 七层模型和 TCP/IP 协议栈是最常见的两种网络通信模型。虽然这两者有些不同&#xff0c;但它们都提供了一种分层的结构&#xff0c;帮助我们理解和设计网络通信。本文将详细介绍…...

synchronize 或者lock 锁常见的使用场景

在 Java 多线程编程中&#xff0c;synchronized 和 Lock&#xff08;如 ReentrantLock&#xff09;是两种常见的线程同步机制。以下是它们的核心区别和典型使用场景&#xff0c;结合代码示例说明&#xff1a; 一、synchronized 的常见场景 1. 简单的临界区保护 public class …...

Redis之缓存更新策略

缓存更新策略 文章目录 缓存更新策略一、策略对比二、常见的缓存更新策略三、如何选择策略四、实际应用示例五、使用 Cache-Aside TTL 的方式&#xff0c;实现缓存商铺信息详情1.引入StringRedisTemplate2.将查询商铺信息加入缓存3.更新商铺信息时移除缓存总结 六、注意事项 一…...

【操作系统学习篇-Linux】进程

1. 什么是进程 课本概念&#xff1a;程序的一个执行实例&#xff0c;正在执行的程序等 内核观点&#xff1a;担当分配系统资源&#xff08;CPU时间&#xff0c;内存&#xff09;的实体。 如果你就看这个来理解进程&#xff0c;那么恭喜你&#xff0c;作为初学者&#xff0c;你…...

Docker 前瞻

一、namespace 指令 1.1 dd 命令 dd 命令用于读取、转换并输出数据。 dd 命令可从标准输入或文件中读取数据&#xff0c;根据指定的格式来转换数据&#xff0c;再输出到文件、设备或标准输出。 语法 dd option if 文件名&#xff1a;输入文件名&#xff0c;默认为标准输入…...

【maxENT】最大熵模型(Maximum Entropy Model)R语言实现

文章目录 一、相关package介绍1.1 dismo 包1.2 raster包1.3 常见问题与解决 二、代码示例 &#x1f7e2;&#x1f7e0;先看&#xff1a;【maxENT】最大熵模型&#xff08;Maximum Entropy Model&#xff09;介绍与使用&#xff08;maxENT软件&#xff09; ASCII文件太大&#…...

高负载WEB服务器--Tomcat

高负载WEB服务器–Tomcat Tomcat介绍 Tomcat 是一个开源的轻量级应用服务器&#xff0c;在 Java Web 应用开发中被广泛使用。 发展历程&#xff1a;Tomcat 最初由 Sun Microsystems 开发&#xff0c;后来成为 Apache 软件基金会的一个项目。它的发展与 Java 技术的发展密切相…...

分页查询列表每页1000条的优化

项目中有一个客户列表,要求每页显示1000条,并且字段很多,接口返回大概要10秒钟,进行优化. 原本逻辑:使用mybatisplus构建查询条件,分页查询客户表,查出数据库DO对象,然后for循环转化成回显的VO对象.在转化的过程中出现了查库代码,导致当每页条数1000时,每一个客户转化都需要查询…...

深入浅出一下Python面向对象编程的核心概念与实践应用

本篇技术博文摘要 &#x1f31f; 本文系统讲解了Python面向对象编程的核心概念与实践应用。通过电商系统用户订单模拟、动态权限账户系统等案例&#xff0c;深入剖析了类与对象、属性方法、实例方法等基础要素。重点解析了__init__构造方法、__str__对象描述、__lt__比较运算符…...

2025阿里云AI 应用-AI Agent 开发新范式-MCP最佳实践-78页.pptx

2025阿里云AI 应用-AI Agent 开发新范式-MCP最佳实践&#xff0c;包含以下内容&#xff1a; 1、AI 应用架构新范式 2、云原生API网关介绍 3、云原生API网关底座核心优势 4、流量网关最佳实践 5、AI 网关代理 LLM 最佳实践 6、MCP网关最佳实践 7、MSE Nacos MCP Server 注册中心…...

github进阶使用教程

目录索引 一、基本内容 repository fork star codespaces issue 在一个仓库创建话题讨论&#xff0c;可以由仓库主人选择开始和结束话题的讨论 pull request&#xff08;也称 pr&#xff09; 协同其他仓库开发&#xff0c;请求仓库主人拉取自己的代码合并到仓库的主分支&…...

【C++】 —— 笔试刷题day_16

刷题_day16&#xff0c;继续加油啊 一、字符串替换 题目解析 这道题是一道简单的字符题目&#xff0c;题目给我们一个字符串A&#xff0c;和n表示A字符串的长度&#xff0c;再给出一个字符数组arg&#xff0c;m表示arg中是数据个数。 然我们在字符串A中找到%s然后替换成arg中的…...

5.3 GitHub订阅系统核心架构解密:高并发设计与SQLite优化实战

GitHub Sentinel 分析报告功能实现:订阅管理核心逻辑解析 关键词:GitHub API 订阅管理, SQLite 数据库设计, RESTful API 开发, 原子操作封装, 异常处理机制 1. 订阅管理功能架构设计 订阅管理模块采用分层架构设计,通过清晰的接口隔离实现高内聚低耦合: #mermaid-svg-bW…...

P5738 【深基7.例4】歌唱比赛

P5738 【深基7.例4】歌唱比赛 题目描述 n ( n ≤ 100 ) n(n\le 100) n(n≤100) 名同学参加歌唱比赛,并接受 m ( m ≤ 20 ) m(m\le 20) m(m≤20) 名评委的评分,评分范围是 0 0 0 到 10 10 10 分。这名同学的得分就是这些评委给分中去掉一个最高分,去掉一个最低分,剩下 …...

从三次方程到复平面:复数概念的奇妙演进(三)

注&#xff1a;本文为 “复数 | 历史 / 演进” 相关文章。 因 csdn 篇幅限制分篇连载&#xff0c;此为第三篇。 生料&#xff0c;不同的文章不同的点。 机翻&#xff0c;未校。 Complex Numbers History: Complex numbers were first introduced by G. Cardano (1501-1576)…...

2025年七星棋牌跨平台完整源码解析(200+地方子游戏+APP+H5+小程序支持,附服务器镜像导入思路)

目前市面上成熟的棋牌游戏源码很多&#xff0c;但能做到平台全覆盖、地方玩法丰富、交付方式标准化的系统却不多。今天这套七星棋牌2023完整源码具备安卓/iOS/H5/微信小程序端四端互通能力&#xff0c;附带200多款地方子游戏&#xff0c;还配备了后台管理与自动热更系统&#x…...

从三次方程到复平面:复数概念的奇妙演进(四)

注&#xff1a;本文为 “复数 | 历史 / 演进” 相关文章合辑。 因 csdn 篇幅限制分篇连载&#xff0c;此为第四篇。 生料&#xff0c;不同的文章不同的点。 机翻&#xff0c;未校。 Complex number and its discovery history 复数及其发现历史 Wenhao Chen, †, Dazheng …...

UE5角色状态机中跳跃落地移动衔接问题

UE5系列文章目录 文章目录 UE5系列文章目录前言一、状态机设置二、主要蓝图 前言 先说说遇到的问题&#xff0c;在我按空格键跳跃落地以后&#xff0c;角色落地再按WSAD键移动就出现了画面中角色抽搐的情况 一、状态机设置 在Unreal Engine 5中创建角色时&#xff0c;处理跳…...

25软考中级*高项网课+历年真题+笔记+电子书+刷题【计算机软考】

两个月逆袭25年软考程序员&#xff1f;这份高效备考指南请收好 25软考中级*高项网课download &#x1f4c2; 软考中级科目备考资料介绍 ✅ 【01】2025 年软件测评师 聚焦软件测试全流程&#xff0c;涵盖 需求分析、测试设计、用例编写、缺陷管理 等核心技能。 &#x1f4d8; 备…...

C++STL——容器-list(含模拟实现,即底层原理)(含迭代器失效问题)(所有你不理解的问题,这里都有解答,最详细)

目录 1.迭代器的分类 2.list的使用 2.1 list的构造 2.2 list iterator 2.3 list capacity 2.4 list element access ​编辑 2.5 list modifiers ​编辑2.5.1 list插入和删除 2.5.2 insert /erase 2.5.3 resize/swap/clear ​编辑 2.6 list的一些其他接口…...

Linux系统编程之虚拟内存

概述 计算机内存是临时存储数据的地方&#xff0c;它比硬盘快得多&#xff0c;但容量有限。现代操作系统通过虚拟内存技术&#xff0c;使得每个进程都感觉自己独占整个地址空间&#xff0c;这不仅提高了安全性&#xff0c;也简化了内存管理。 物理内存&#xff1a;实际安装在计…...

笔试专题(八)

文章目录 平方数&#xff08;数学&#xff09;题解代码 DNA序列&#xff08;固定长度的滑动窗口&#xff09;题解代码 压缩字符串 &#xff08;双指针 模拟&#xff09;题解代码 chika和蜜柑 &#xff08;top k问题 排序 pair&#xff09;题解代码 平方数&#xff08;数学&a…...