Linux环境基础开发工具使用

目录

1.Linux软件包管理器yum

什么是软件包

关于 lrzsz

查看软件包

2.Linux开发工具

2.1.vim的基本概念

2.2vim的基本操作

2.3vim命令模式命令集

1.插入模式

2.从插入模式切换为命令模式

3.移动光标

4.删除文字

5.复制

6.替换

7.撤销上一次的操作

8.更改

2.4vim低行模式命令集

2.5简单vim配置

2.6如何进行给普通用户提权

3.Linux编译器-gcc/g++使用

4.Linux项目自动化构建工具-make/Makefile

生成多个可执行程序的写法

5.Linux调试器 gdb 的使用

1.背景

readelf指令

2.开始使用

6.Linux第一个小程序 - 进度条

5.1\r(回车)和\n(换行)的概念

5.2行缓冲区概念

5.3进度条代码及批量注释的方法

7.使用git的命令行

1.Linux软件包管理器yum

什么是软件包

在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序,但是这样太麻烦了, 于是有些人把一些常用的软件提前编译好, 做成软件包(可以理解成windows上的安装程序)放在一个服务器上, 通过包管理器可以很方便的获取到这个编译好的软件包, 直接进行安装。
软件包和软件包管理器, 就好比 "App" 和 "应用商店" 这样的关系,yum(Yellow dog Updater, Modified)是Linux下非常常用的一种包管理器. 主要应用在Fedora, RedHat,Centos等发行版上。

Linux安装软件三种方式:

1.源代码安装,这种方式对于普通用户来说操作难度太高不适合。

2.rpm安装 -- Linux安装包,需要主动解决下面第三种方式的那些问题。

3.yum安装 -- 自动解决安装源,安装版本,安装依赖。(推荐使用yum安装软件)

关于 lrzsz

这个工具用于 windows 机器和远端的 Linux 机器通过 XShell 传输文件.安装完毕之后可以通过拖拽的方式将文件上传到远程主机

输入命令rz会自动跳出一个窗口用来上传文件,也就是把文件发送到远程主机(如:Linux)。

输入命令 sz [文件名],可以把文件发送到本地主机(如:Windows)。

注:0kb的文件有可能无法进行上传。

注意事项

关于 yum 的所有操作必须保证主机(虚拟机)网络畅通!!!

可以通过 ping 指令验证,输入:ping www.baidu.com

查看软件包

通过 yum list 命令可以罗列出当前一共有哪些软件包. 由于包的数目可能非常之多, 这里我们需要使用 grep 命令只筛选出我们关注的包. 例如:

yum list | grep lrzsz

结果如下:

lrzsz.x86_64          0.12.20-36.el7            @base

注意事项:

软件包名称: 主版本号.次版本号.源程序发行号-软件包的发行号.主机平台.cpu架构.
"x86_64" 后缀表示64位系统的安装包, "i686" 后缀表示32位系统安装包. 选择包时要和系统匹配.
"el7" 表示操作系统发行版的版本. "el7" 表示的是 centos7/redhat7. "el6" 表示 centos6/redhat6.
最后一列, base 表示的是 "软件源" 的名称, 类似于 "小米应用商店", "华为应用商店" 这样的概念

如何安装软件:

通过 yum, 我们可以通过很简单的一条命令完成 lrzsz 的安装

sudo yum install lrzsz

yum 会自动找到都有哪些软件包需要下载, 这时候敲 "y" 确认安装,出现 "complete" 字样, 说明安装完成。

注意事项:

安装软件时由于需要向系统目录中写入内容, 一般需要 sudo 或者切到 root 账户下才能完成.
yum安装软件只能一个装完了再装另一个. 正在yum安装一个软件的过程中, 如果再尝试用yum安装另外
一个软件, yum会报错,如果 yum 报错, 请自行百度。

如何卸载软件:

仍然是只需要一条命令:

sudo yum remove lrzsz

在卸载的时候会提示是否确认卸载已安装软件,这时候敲 "y" 确认卸载,不过在输入命令的时候输入-y选项则会不跳出提示直接卸载,安装软件的时候也可以携带-y选项。

2.Linux开发工具

Linux编辑器-vim使用

vi/vim的区别简单点来说,它们都是多模式编辑器,不同的是vim是vi的升级版本,它不仅兼容vi的所有指令,而且还有一些新的特性在里面。例如语法加亮,可视化操作不仅可以在终端运行,也可以运行于x window、 mac os、windows。

2.1.vim的基本概念

vim其实有很多种模式,但是我们目前只需要掌握vim的三种模式即可,这三种模式分别是:命令模式(command mode)、插入模式(Insert mode)和底行模式(last line mode),各模式的功能区分如下:

1.正常/普通/命令模式(Normal mode)

当我们使用vim指令打开进入一个源文件时,默认的就是命令模式,命令模式可以控制屏幕光标的移动、字符、字或行的删除,移动复制某区段及进入Insert mode(插入模式)下,或者到 last line mode(低行模式)。

2.插入模式(Insert mode)
只有在Insert mode下,才可以做文字输入,按「ESC」键可回到命令行模式。该模式是我们后面用的最频繁的编辑模式。

3.末行/低行模式(last line mode)

文件保存或退出,也可以进行文件替换,找字符串,列出行号等操作。 在命令模式下,shift+: 即可进入该模
式。要查看你的所有模式:打开vim,底行模式直接输入:help vim-modes

我们这里一般一共有12种模式:six BASIC modes和six ADDITIONAL modes。

2.2vim的基本操作

1.进入vim,在系统提示符号输入vim及文件名称后,就进入vim全屏幕编辑画面:

$ vim test.c //实列
//不过有一点要特别注意,就是你进入vim之后,是处于[正常模式],你要切换到[插入模式]才能够输入文字

2.在[正常模式]切换至[插入模式]

输入a
输入i
输入o
输入s
//四种方法

3.在[正常模式]切换至[末行模式]

「shift + :」//分号冒号都可以

退出vim及保存文件,在[正常模式]下,按一下「shift + :」键进入「Last line mode」,然后输入:

w (保存当前文件)
wq (输入「wq」,存盘并退出vim)
wq! (输入「wq」,存盘并强制退出vim)
q  (输入q,不保存退出)
q! (输入q!,不存盘(不保存)强制退出vim)

当切换到其他模式时又该怎么回到正常模式?从其他模式回到正常模式按 [ESC] 键,不管在什么模式底下都应该先切换回正常模式再去切换到其他模式。

注:

注:在使用vim直接进入一个不存在的文件时,在编辑完之后如果不进行保存是不会留下来的,只有保存之后文件才有被留下。

2.3vim命令模式命令集

1.插入模式
按「i」切换进入插入模式「insert mode」,按“i”进入插入模式后是从光标当前位置开始输入文件。
按「a」进入插入模式后,是从目前光标所在位置的下一个位置开始输入文字。
按「o」进入插入模式后,是插入新的一行,从行首开始输入文字。
按「s」进入插入模式后,是删除当前光标所在的字符,并从这个字符位置开始输入文字。
2.从插入模式切换为命令模式
按「ESC」键。
3.移动光标
gg:定位光标到最开始行
shift + g:定位光标到最结尾行 //实际上是大写的G,因为小写的g + shift就是大写的G
n + shift + g:定位光标到任意行 // 可以变换成n + G
h、j、k、l:分别代表左、下、上、右(虽然方向键也可以进行移动光标,不过在使用习惯hjkl回方便点)
w、b:光标安装单词进行行内跨行进行移动
e:光标跳到下个字的字尾
n + l:光标移到该行的第n个位置
shift + ^:定位光标到但前行开始
shift + $:定位光标到当前行结尾
ctrl + b:屏幕往“后”移动一页
ctrl + f:屏幕往“前”移动一页
ctrl + u:屏幕往“后”移动半页
ctrl + d:屏幕往“前”移动半页
注:带有shift和ctrl的命令需要一起按,数字不用和命令一起按,n代表要输入的数字,
可以先输入数字在去按命令
4.删除文字
x:每按一次,删除光标所在位置的一个字符 //小写
n + x:例如,「6x」表示删除光标所在位置的“后面(包含自己在内)”6个字符 //小写
X:大写的X,每按一次,删除光标所在位置的“前面”一个字符 //大写
n + X:例如,「20X」表示删除光标所在位置的“前面”20个字符 //大写
dd:剪切光标所在行
n + dd:从光标所在行开始剪切#行
5.复制
yw:将光标所在之处到字尾的字符复制到缓冲区中。
n + yw:复制#个字到缓冲区
yy:复制光标所在行到缓冲区。
n + yy:例如,「6yy」表示拷贝从光标所在的该行“往下数”6行文字。
p:将缓冲区内的字符贴到光标所在位置。注意:所有与“y”有关的复制命令都必须与“p”配合才能完
成复制与粘贴功能。
n + p:重复粘贴n行,粘贴到光标所在的下一行
6.替换
r:替换光标所在处的字符。
n + r:对光标字符 + 之后的所有字符进行批量替换
R:替换光标所到之处的字符,直到按下「ESC」键为止。 //第四种模式 -- 替换模式,对内容整体替换
shift + ~:大小写转换
7.撤销上一次的操作
u:如果您误执行一个命令,可以马上按下「u」,回到上一个操作。按多次“u”可以执行多次回复。
ctrl + r: 撤销的恢复
8.更改
「cw」:更改光标所在处的字到字尾处,并进入插入模式
「c#w」:例如,「c3w」表示更改3个单词,并进入插入模式

2.4vim低行模式命令集

在使用末行模式之前,请记住先按「ESC」键确定您已经处于正常模式,再按[shift + :]即可进入末行模式。

1.列出行号

set nu: 输入「set nu」后,会在文件中的每一行前面列出行号
set nonu: 输入「set nonu」后,取消每一行前面列出的行号

2.跳到文件中的某一行

[#]: #号表示一个数字,在冒号后输入一个数字,再按回车键就会跳到该行了,如输入数字15,
再回车,就会跳到文章的第15行。

3.查找字符

1.[/]关键字: 先按 / 键,再输入您想寻找的字符,如果第一次找的关键字不是您想要的,可以一直按
n 会往后寻找到您要的关键字为止。
2.[?]关键字:先按 ? 键,再输入您想寻找的字符,如果第一次找的关键字不是您想要的,可以一直
按 n 会往前寻找到您要的关键字为止。
问题:/ 和 ?查找有和区别?操作实验一下

4.保存文件

「w」: 在冒号前输入字母「w」就可以将文件保存起来

5.离开vim

「q」:按「q」就是退出,如果无法离开vim,可以在「q」后跟一个「!」强制离开vim。
「wq」:一般建议离开时,搭配「w」一起使用,这样在退出的时候还可以保存文件。同上,无法
退出是也可以在后面加上[!]表示强制退出。

6.多文件操作

vs + [文件名] :打开多个文件编辑窗口,如果该文件不存在会直接新建一个文件
ctrl + ww :窗口光标切换,光标在哪一个窗口界面就对那一个窗口进行操作。
注:在多文件窗口操作下可以把另一个窗口的代码复制粘贴过来。

7.执行外部指令

!+ [对应的指令] :比如:! ls 

8.快速删除全部内容

%d:快速删除文件内的所有内容

2.5简单vim配置

配置文件的位置

在目录 /etc/ 下面,有个名为vimrc的文件,这是系统中公共的vim配置文件,对所有用户都有效。
而在每个用户的主目录下,都可以自己建立私有的配置文件,命名为:“.vimrc”。例如,/root目录下,
通常已经存在一个.vimrc文件,如果不存在,则创建之 touch .vimrc。
切换用户成为自己的用户执行 su ,进入自己的主工作目录,执行 cd ~
打开自己目录下的.vimrc文件,执行 vim .vimrc

只要在命令行执行以下命令即可:

curl -sLf https://gitee.com/HGtz2222/VimForCpp/raw/master/install.sh -o./install.sh && bash ./install.sh

注:目前只支持 centos 7.X

2.6如何进行给普通用户提权

当普通用户在想给某一条命令进行提升权限时可以在该命令前面加上sudo,但是由于系统不信任你无法给命令进行提权,因为该用户不在系统的信任白名单里,所以想要把普通用户添加到系统信任白名单里就需要使用root用户来把想要的普通用户添加进白名单里,把用户添加进/etc/sudoers这个路径底下的sudoers文件里,操作:

3.Linux编译器-gcc/g++使用

yum install gcc //安装gcc
yum -y install gcc gcc-c++ kernel-devel //安装g++

gcc只能编译C语言,g++既能编译C语言又可以编译C++,如果使用gcc去编译c++文件会显示错误,而且它们的操作是一样的只需要学会使用g++即可。

注:使用 ./ 可以执行生成的可执行程序 或者 路径携带可执行程序名。如:./a.out 和 /home/kuro/a.out ,两种方式。

函数库一般分为静态库和动态库两种:

静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a”
动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”,如前面所述的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件,如下所示:gcc hello.o –o hello
gcc默认生成的二进制程序,是动态链接的,这点可以通过 file 命令验证。

gcc/g++选项:

-E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面
-S 编译到汇编语言不进行汇编和链接
-c 编译到目标代码
-o 文件输出到 文件
-static 此选项对生成的文件采用静态链接
-g 生成调试信息。GNU 调试器可利用该信息。
-shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.
-O0
-O1
-O2
-O3 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
-w 不生成任何警告信息。
-Wall 生成所有警告信息。

debug&&release

Linux默认生成的可执行程序是以release版本发布的,以debug版本发布的可执行程序可以被追踪和调试,因为形成可执行程序的时候,添加了debug信息,在未来做开发的时候如果需要可以添加上 -g 选项发布debug版本。

4.Linux项目自动化构建工具-make/Makefile

背景

1.会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力(首字母可以大写也可以小写)
2.一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
3.makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
4.make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
5.make是系统携带的一条命令,makefile是一个当前目录的文件(目录的开头字母可以大写也可以小写),两个搭配使用,完成项目自动化构建。

例子:

原理:

make是如何工作的,在默认的方式下,也就是我们只输入make命令。那么:

1. make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
2. 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“mycode”这个文件,并把这个文件作为最终的目标文件。
3. 如果mycode文件不存在,或是mycode所依赖的后面的mycode.o文件的文件修改时间要比hello这个文件新(可以用 touch 测试),那么,他就会执行后面所定义的命令来生成mycode这个文件。
4. 如果mycode所依赖的mycode.o文件不存在,那么make会在当前文件中找目标为mycode.o文件的依赖性,如果找到则再根据那一个规则生成mycode.o文件。(这有点像一个堆栈的过程)
5. 当然,你的.c文件和.h文件是存在的啦,于是make会生成 mycode.o 文件,然后再用 mycode.o 文件声明make的终极任务,也就是执行文件mycode了。
6. 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
7. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。
8. make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。

生成多个可执行程序的写法

.PHONT:all
all:server client//表示生成多个可执行程序

server:server.cc
	g++ -o $@ $^ -std=c++11
client:client.cc
	g++ -o $@ $^ -std=c++11

.PHONY:clean
clean:
	rm -rf server client

在这个Makefile中,.PHONY 声明了 all 和 clean 是伪目标。

all: server client 表示 all 目标依赖于 server 和 client。在一个Makefile中,目标"all"通常用来定义一个伪目标,并作为默认目标。当用户在命令行中运行"make"命令时,如果没有指定目标,默认会执行"all"目标下的命令。

因此,"all"目标可以用来定义构建或编译整个项目所需的命令。通过指定"all"目标,可以方便用户一次性构建整个项目,而不需要手动执行多个目标或命令。

server: server.cc 表示 server 目标依赖于 server.cc 这个文件。

g++ -o $@ $^ -std=c++11 是编译 server 目标的命令,其中 $@ 表示目标名(即 server),$^ 表示所有的依赖文件(即 server.cc),-std=c++11 是指定使用 C++11 标准进行编译。

类似地,client: client.cc 和 g++ -o $@ $^ -std=c++11 定义了编译 client 目标的规则。

.PHONY: clean 表示 clean 是一个伪目标。

clean: rm -rf server client 定义了一个规则,用于执行清理操作,即删除 server 和 client 这两个可执行文件。

什么是伪目标?

伪目标是Makefile中的一种特殊目标。它不是一个真正的文件目标,而是作为一个标志或命令的名称存在,用于标识某些特定的操作或规则。

伪目标通常被用来执行一些非文件类型的操作,比如清理临时文件、生成文档、运行测试等。它们在Makefile中以`.PHONY`声明,并且不会被Make工具当作真正的文件目标来处理。

伪目标的好处是,即使源文件被更新或存在时,它们也会被强制执行,从而保证所需操作的执行。此外,伪目标还可以作为命令行参数直接执行,而不需要指定文件作为目标。

以下是一个使用伪目标的示例:

```

.PHONY: clean

clean:

rm -rf *.o

```

在这个示例中,`clean`是一个伪目标,用于删除所有`.o`文件。当执行`make clean`命令时,Make工具会执行相应的命令,而不会检查是否存在`clean`文件。

5.Linux调试器 gdb 的使用

yum install gdb//安装gdb

1.背景

程序的发布方式有两种,debug模式和release模式
Linux的gcc/g++编译出来的二进制程序,默认是release模式
要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g 选项。(也就是说在使用gcc/g++编译生成可执行程序时带上-g选项即可)

注:携带 -g 选项时,不能放在其他选项和要形成的文件中间,要么放在他们的前面,要么就放在他们的后面

readelf指令

readelf是一个用于查看ELF(可执行与可链接格式)文件的工具,它在Linux系统中可用。readelf指令提供了一种查看可执行文件、共享库和目标文件的结构、节(section)、符号表、头部信息等的方式。

常见的用法包括:

  1. 查看ELF文件的头部信息: readelf -h <elf文件名> 这将显示ELF文件的基本头部信息,包括ELF文件的类型、机器架构、入口地址、节表偏移等。
  2. 查看ELF文件的节(section)信息: readelf -S <elf文件名> 这将显示ELF文件中的节(section)表信息,包括节的名称、大小、虚拟地址、偏移等。
  3. 查看ELF文件的符号表信息: readelf -s <elf文件名> 或 readelf -S <elf文件名> 这将显示ELF文件的符号表信息,包括全局符号、局部符号、符号的名称、类型、绑定、地址等。
  4. 查看ELF文件的动态节(dynamic section)信息: readelf -d <elf文件名> 这将显示ELF文件的动态节信息,包括动态链接信息、动态符号表信息、共享对象信息等。

除了上述常见用法外,readelf还提供了其他选项和功能,如查看重定位表信息、显示程序头表信息、显示动态符号表信息等,可以使用 readelf --help 命令查看更多用法和选项。

需要注意的是,readelf指令只能用于查看ELF文件,不能用于查看其他格式的可执行文件或库文件。

2.开始使用

注:使用前需要通过 yum install -y gdb,进行安装gdb。

gdb 模式退出退出指令: ctrl + d 或 quit/q

调试命令:

list/l + 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。
//注:gdb会记住我们最近输入的一条指令,想继续使用上一条指令直接回车即可。
list/l + 函数名:列出某个函数的源代码。
r或run:开始运行程序进行调试。	 //类似vs的F5,唯一不一样的地方是每次输入r只会程序运行重新,会提示是否
//需要重新运行程序,不会和vs一样跳到下一个断点,只有第一次会跳到附件最近的断点处

n 或 next:单条执行。 //相当于vs的F10:逐过程,并且会显示当前所在行
s或step:进入函数调用 //类似于vs的F11:逐语句,并且会显示当前所在行
//他们两个不能直接使用,需要配合r开始运行和设置断点之后才会逐条执行代码
//s或step不建议乱用,只有当前行处于函数所在行时再使用,否则会跳转到其他的库中,特别是c++的代码中
//如果当前行的代码包含有C++的 类 或者 库函数,也会进行跳转!

break / b + 行号:在某一行设置断点
break / b + 函数名:在某个函数开头设置断点
info / i + break :查看断点信息。
delete breakpoints:删除所有断点
delete breakpoints n:删除编号为n的断点	//delete breakpoints可以简写为delete或者d
print(p):打印表达式的值,通过表达式可以修改变量的值或者调用函数
p + 变量名:打印变量值。
info / i + locals:查看当前函数栈帧的所有局部变量的值
display + 变量名:跟踪查看一个变量,每次停下来都显示它的值 //类似vs监视窗口,并且跟踪的变量有对应的编号
undisplay + n(n:追踪变量的编号):取消对先前设置的某个编号变量的跟踪 //n 表示对应的编号
set var + 变量名:修改变量的值//列如修改追踪变量的值,如果在循环中修改变量的值,可以加快循环次数。
until + X行号:跳至X行	//可以用来跳出循环
finish:执行到当前函数返回,然后停下来等待命令 //执行完当前行的函数,并返回到当前行,顺带显示结果
continue(或c):从当前位置开始连续而非单步执行程序	//直接跳到下一个断点处
disable breakpoints + 断点编号:禁用断点		//disable breakpoints可以缩写为disable
enable breakpoints + 断点编号:启用断点		//enable breakpoints可以缩写为enable
info(或i) breakpoints:参看当前设置了哪些断点
breaktrace / bt:查看各级函数调用及参数		//相当于vs的函数调用栈,可以查看各个函数的调用顺序
//"bt"命令默认打印的是简化的函数调用栈,即只显示函数名和行号。而使用"bt full"命令则
//会打印更详细的函数调用栈信息,包括函数的参数和局部变量。
f + 函数编号:可以直接运行跳转到对应的函数,一般配合bt查看函数编号使用,输入bt时第一列信息就是函数的编号
quit/ q / ctrl + d:退出gdb

注:在使用 run/r 开始运行程序调试时,需要先使用b打上断点,让它停在断点行,否则会直接运行程序到结束。

6.Linux第一个小程序 - 进度条

5.1\r(回车)和\n(换行)的概念

\r和\n都是特殊字符,但它们有着不同的含义和使用方式。

\r代表回车(Carriage Return),它将光标移到当前行的开头,相当于按下回车键但不换行。在编程语言中,通常使用\r来表示回车符。

\n代表换行(Line Feed),它将光标移到下一行的开头。在编程语言中,通常使用\n来表示换行。

("\n"是C语言中的换行符,它的作用是在输出中插入一个换行符。当程序执行到输出语句中的"\n"时,它会将之前的所有输出内容刷新(清空)缓冲区,并将缓冲区中的内容输出到屏幕上。)

5.2行缓冲区概念

行缓冲区(Line Buffer)是一种特殊的缓冲区,用于存储和处理文本数据中的一行内容。它通常用于输入输出流的数据处理,特别是与终端设备(如终端窗口或控制台)交互式输入输出时。

行缓冲区的特点是在缓冲区收到换行符('\n')之前,不会立即将数据发送给终端或处理。相反,它会将数据存储在缓冲区中,等待一行内容完整后再进行处理。

具体来说,当程序向行缓冲区写入数据时,这些数据不会立即显示在终端上,而是存储在缓冲区中,直到满足以下条件之一时才会刷新缓冲区:

  • 缓冲区已满,无法再存储更多的数据。
  • 遇到换行符('\n')时,会自动触发刷新缓冲区,将缓冲区中的数据发送到终端显示。
  • 调用fflush()函数显式刷新缓冲区。

行缓冲区的使用可以提高交互式输入输出的效率,因为用户输入的一行内容通常是一次性输入的,等待换行符触发刷新缓冲区可以提供更好的用户体验。

需要注意的是,行缓冲区只适用于终端设备的输入输出,默认情况下,文件操作和管道操作使用的是全缓冲区(Full Buffer)或无缓冲区(Unbuffered)。

在C语言中,标准输入流(stdin)、标准输出流(stdout)和标准错误流(stderr)默认使用行缓冲区。

总结来说,行缓冲区是一种特殊的缓冲区,用于存储和处理输入输出流中的一行内容,直到遇到换行符或缓冲区已满时才会触发刷新。它可以提高交互式输入输出的效率。

5.3进度条代码及批量注释的方法

//main.c
#include "processbar.h"
#include <unistd.h>

typedef void (*callback_t)(int);//定义一个函数指针类型

//模拟某一种安装或者下载
void downLoad(callback_t cb)
{
	int total = 1000;//1000Mb
	int curr = 0;//0Mb
	while(curr <= total)
	{
		//假设进行着某种下载的任务
		usleep(50000);//模拟下载花费的时间
		int rate = curr*100/total;//更新进度
		
		cb(rate);//通过回调,展示进度

		curr += 10;//循环下载了一部分
	}
	printf("\n");
}

int main()
{
	//v2
	printf("downLoad 1:\n");
	downLoad(processbar);
	initbar();

	printf("downLoad 2:\n");
	downLoad(processbar);
	initbar();

	printf("downLoad 3:\n");
	downLoad(processbar);
	initbar();

	//v1
	//processbar(50000);


	//倒计时小程序
	//int cnt = 10;
	//while(cnt >= 0)
	//{
	//	printf("%-2d\r", cnt);
	//	fflush(stdout);
	//	cnt--;
	//	sleep(1);
	//}
	//printf("\n");
	//
	//printf("hello world");
	//fflush(stdout);
	//sleep(2);
	//批量注释:
	//先使用ctrl + v进入列选择模式(VISUAL BLOCK),
	//然后使用方向键选中需要注释的行,接着按大写的I键
	//进入插入模式,输入注释符(//)之后,双击ESC即可完成注释
	
	return 0;
}
//processbar.c
#include "processbar.h"
#include <string.h>
#include <unistd.h>

//v2:进度条是如何调用的
const char* lable = "|/-\\";
char bar[NUM];

void processbar(int rate)
{
	if(rate < 0 || rate > 100)
		return;

	int len = strlen(lable);
	printf("[%-100s][%d%%][%c]\r", bar, rate, lable[rate%len]);
	fflush(stdout);
	bar[rate++] = BODY;
	if(rate < 100 )
		bar[rate] = RIGHT;
}

void initbar()
{
	memset(bar, '\0', sizeof(bar));
}

//v1
//const char* lable = "|/-\\";
//
//void processbar(int speed)
//{
//	int cnt = 0;
//	char bar[NUM];
//	memset(bar, '\0', sizeof(bar));
//	int len = strlen(lable);
//
//	while(cnt <= TOP)
//	{
//		printf("[%-100s][%d%%][%c]\r", bar, cnt, lable[cnt%len]);
//		bar[cnt++] = BODY;
//		if(cnt < TOP)
//			bar[cnt] = RIGHT;
//
//		fflush(stdout);
//		usleep(speed);//微秒
//	}
//
//	printf("\n");
//}
//processbar.h
#pragma once

#include<stdio.h>

#define NUM 102
#define TOP 100
#define BODY '='
#define RIGHT '>'

//v2
extern void processbar(int rate);
extern void initbar();

//v1
//extern void processbar(int speed);
//makefile
processbar:processbar.c main.c
	g++ $^ -o $@
.PHONY:clean
clean:
	rm -f processbar

7.使用git的命令行

首先我们要先去安装git

指令:yum install git

//1.把仓库克隆到本地
git clone [url]//url:网址
//注:也可以使用第一步把别人开源的仓库 拉取/克隆 下来到本地
//2.把需要的提交的文件拷贝到刚才克隆下来的本地仓库(目录)
git add . // . 表示当前目录,或者. 可以改为[文件名],也就是单独的某一个文件,这个操作就是
//将需要用 git 管理的文件告知 git 然后使用以下命令行:
git commit -m ""  //这个操作我们必须携带-m,然后双引号里面必须写一些对应的信息,这个
//信息叫做提交日志,这个提交日志不能胡写,必须写我们做了什么或者完成了什么。 
//这个 git commit -m "" 操作就是将告知git的文件添加到本地仓库里,之前只是拷贝不算是添加
    
//3.推送/同步到远端服务器上的仓库
git push
//如果显示需要输入用户名和密码就是登录gitee的账号和密码
//如果不知道用户名是哪个,可以打开网页登录git,查看上方的网址的后缀部分就是用户名

执行完上面的步骤如果显示有文字则说明同步成功:

注:如果在执行第二部跳出以下提示:

因为git首次使用需要配置邮箱和用户名,git要知道你是谁,主要是为了方便溯源,这样才知道是谁写的代码,代码出了问题的时候才好找到对方。命令执行失败的原因是没有在本地设置用户名和邮箱,在命令行设置一下即可:

git config –global user.email 'you@example.com'
git config –global user.name 'Your name'

上面的方法配置的是它提供全局的用户名和邮箱,就是说如果没有单独为项目配置(当前本地仓库),那提交的所有项目全部都是这个名字和邮箱!

单独为项目配置的方法(全局和单独配置都存在的时候会默认优先使用项目单独配置的):

  1. 打开项目所在目录(本地仓库目录),进入这个隐藏的 .git 文件夹。这个文件夹是隐藏的,显示隐藏出来就行。
  2. 打开文件夹里的config文件,可以使用vim打开这个文件。
  3. 添加这三行到文件的空白位置:
[user]//这个不用改
name = XXX(自己的名称)
email = XXX(邮箱)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/428610.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Windows10笔记本亮度调节按键失灵

操作&#xff1a;任务管理器 -> 监视器 -> 右键点击 -> 通用即插即用监视器 -> 更新驱动程序 -> 浏览我的电脑以查找我的驱动程序 -> 让我从计算机上的可用驱动程序列表中选取 -> 点击通用即插即用监视器 -> 点击关闭 -> 重启电脑。 第一步&#x…

第三百八十二回

文章目录 1. 概念介绍2. 使用方法3. 代码与效果3.1 示例代码3.2 运行效果 4. 内容总结 我们在上一章回中介绍了"如何修改按钮的形状"相关的内容&#xff0c;本章回中将介绍NavigationBar组件.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在本章…

波奇学Linux:进程通信之命名管道

进程通信的前提&#xff1a;让不同的进程看到同一份文件 匿名管道只能具有血缘关系的进程&#xff0c;毫不相关的进程通信得要命名管道 管道文件不需要刷盘&#xff0c;基于内存级文件 命名管道通过路径文件名确定打开同一个文件&#xff0c;在匿名管道中利用父子进程。 创…

(学习日记)2024.02.29:UCOSIII第二节

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

总结:React 中的 state 状态

☝️上文提及&#xff1a;可以通过组件中的重要信息是否由组件自身 state 还是外部 prop 驱动来区分「受控组件」&「非受控组件」。 换言之&#xff0c;props 是对外的&#xff0c;state 是对内的 props&#xff1a;只读&#xff0c;父组件通过 props 传递给子组件其所需要…

AI预测福彩3D第一弹【2024年3月4日预测】

众所周知&#xff0c;深度学习算法&#xff08;AI算法&#xff09;由于其内部含有庞大数量的神经元&#xff0c;理论上能够拟合任意维度的数据&#xff0c;目前在大数据分析领域应用非常广泛&#xff0c;并且能够很好的挖掘数据规律&#xff0c;对相关数据进行预测分析。 前面一…

Tomcat源码解析(二): Bootstrap和Catalina

Tomcat源码系列文章 Tomcat源码解析(一)&#xff1a; Tomcat整体架构 Tomcat源码解析(二)&#xff1a; Bootstrap和Catalina 目录 前言一、启动类Bootstrap1、main2、init3、load与start 二、加载Catalina1、load2、start2.1、注册shutdown钩子2.2、监听shutdown命令2.3、停止…

从零开始学习Netty - 学习笔记 -Netty入门【协议设计和解析】

2.协议设计和解析 协议 在计算机中&#xff0c;协议是指一组规则和约定&#xff0c;用于在不同的计算机系统之间进行通信和数据交换。计算机协议定义了数据传输的格式、顺序、错误检测和纠正方法&#xff0c;以及参与通信的各个实体的角色和责任。计算机协议可以在各种不同的层…

【PCL】 (十六)点云距离图可视化

&#xff08;十六&#xff09;点云距离图可视化 以下代码实现点云及其对应距离图的可视化。 数据样例&#xff1a;sphere100.pcd range_image_visualization.cpp #include <iostream>#include <pcl/range_image/range_image.h> #include <pcl/io/pcd_io.h&g…

C++11常用知识分享(二)【可变参数模板 || lambda表达式 || 包装器】

目录 一&#xff0c;可变参数模板 1. 递归方法展开参数包 2. 逗号表达式展开参数包 3&#xff0c;可变参数模板优势 二&#xff0c;lambda表达式 1. lambda表达式语法 2. 注意点 三&#xff0c;包装器 1. bind(了解) 嗨&#xff01;收到一张超美的风景图&#xff0c;希…

C向C++的一个过渡

思维导图 输入输出&#xff0c;以及基础头文件 在c语言中我们常用scanf("%d",&n);和printf("%d\n",n);来输出一些变量和常量&#xff0c;在C中我们可以用cin;和cout;来表示输入输出。 在C语言中输入输出有头文件&#xff0c;在C也有头文件&#xff0…

#WEB前端(CCS选择器)

1.实验&#xff1a;CCS选择器 2.IDE&#xff1a;VSCODE 3.记录&#xff1a; 子代选择器、后代选择器、相邻兄弟选择器、类选择器、伪元素选择器&#xff08;鼠标悬停&#xff09;、ID选择器、调用选择器&#xff08;全选&#xff09; 4.代码&#xff1a; <!DOCTYPE html…

Vue.js 实用技巧:深入理解 Vue.set 方法

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

JMeter常用函数整理

"_csvRead"函数 csvRead函数是从外部读取参数&#xff0c;csvRead函数可以从一个文件中读取多个参数。 下面具体讲一下如何使用csvread函数&#xff1a; 1.新建一个csv或者text文件&#xff0c;里面保存要读取的参数&#xff0c;每个参数间用逗号相隔。每行表示每一组…

MATLAB:Image Processing Toolbox工具箱入门实战

目录 1.基本图像导入、处理和导出 2.实战项目一&#xff1a;利用imfindcircles()函数检测和测量图像中的圆形目标 1.基本图像导入、处理和导出 Basic Image Import, Processing, and Export- MATLAB & SimulinkThis example shows how to read an image into the worksp…

BUUCTF---[极客大挑战 2019]Http1

1.题目描述&#xff0c;在地址框输入下面的网址 2.来到页面&#xff0c;ctrlu查看源码&#xff0c;仔细观察会看到一个.php的跳转页面 3.点进去页面提示It doesnt come from https://Sycsecret.buuoj.cn 4.页面提示它不是来源于这个网址&#xff0c;我们需要用bp抓包对数据进行…

从0到1全流程使用 segment-anything

从0到1全流程使用 segment-anything 一、安装 anaconda 一、下载 anaconda 二、以管理员身份运行安装 1、勾选 Just Me 2、统一安装路径(后续 python 等包也安装至此目录) 3、勾选 add to path 然后安装即可。 三、修改 Anaconda 默认路径及默认缓存路径 Anaconda 默认下…

神经网络3-时间卷积神经网络

在深度学习的知识宝库中&#xff0c;卷积神经网络&#xff08;CNN&#xff09;广泛应用于视觉&#xff0c;视频等二维或者多维的图像领域。卷积网络具有深度&#xff0c;可并行等多种优良特性&#xff0c;那么这种技术是否可以应用于解单维度的时间序列问题呢&#xff1f;本文介…

基于Springboot的助农管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的助农管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&…

UTONMOS元宇宙游戏发展趋势是什么?

UTONMOS元宇宙游戏的发展趋势包括以下几个方面&#xff1a; 更加真实的体验&#xff1a;随着技术的进步&#xff0c;UTONMOS元宇宙游戏将提供更加逼真的视觉、听觉和触觉体验&#xff0c;让玩家更加身临其境。 社交互动&#xff1a;UTONMOS元宇宙游戏将越来越注重社交互动&am…
最新文章