一.Linux系统中安装软件方法1.源码安装2.软件包安装---rpm/deb3.包管理器yum(centos) apt/apt-get(ubuntu)推荐a.网络下载b.安装拷贝只能使用root权限进行软件包管理器什么是软件包• 在Linux下安装软件, ⼀个通常的办法是下载到程序的源代码, 并进⾏编译, 得到可执⾏程序.• 但是这样太⿇烦了, 于是有些⼈把⼀些常⽤的软件提前编译好, 做成软件包(可以理解成windows上的安装程序)放在⼀个服务器上, 通过包管理器可以很⽅便的获取到这个编译好的软件包, 直接进⾏安装.• 软件包和软件包管理器, 就好⽐ App 和 应⽤商店 这样的关系.• yum(Yellow dog Updater, Modified)是Linux下⾮常常⽤的⼀种包管理器. 主要应⽤在Fedora,RedHat, Centos等发⾏版上.• Ubuntu主要使⽤aptAdvanced Package Tool作为其包管理器。apt同样提供了⾃动解决依赖关系、下载和安装软件包的功能。二.Linux的生态1.Linux下载软件的过程2.如何去评估一个操作系统的好坏生态评估包含以下几个方面3.为什么会有⼈免费特定社区提供软件还发布还提供云服务器让你下载图解开源本质就是一种商业模式4.软件包依赖的问题5.镜像定义镜像指一个物体、图像、数据或系统以对称轴 / 对称面为基准形成左右相反、结构完全一致的复刻副本内容与原对象完全相同仅空间方向反转。镜像站点完全同步主站数据的备用服务器用于分流、加速访问、容灾备份。大白话就是现在的很多云服务都是外国的社区发明的国内上基本用不了但其中不乏有一些国内的成员在里面就想办法通过一些方式让国内也可以用这种方式就叫做镜像三.apt的具体操作这里面是ubuntu系列所以是apt,centos是yum操作1. 查看软件包通过 yum list 命令可以罗列出当前⼀共有哪些软件包. 由于包的数⽬可能⾮常之多, 这⾥我们需要使⽤grep 命令只筛选出我们关注的包.2. 安装软件通过 apt/yum, 我们可以通过很简单的⼀条命令完成 gcc 的安装.#Centossudo yum install -y lrzsz#Ubuntusudo apt install -y lrzsz备注yum/apt 会⾃动找到都有哪些软件包需要下载, 这时候敲 y 确认安装. 出现 complete 字样或者中间未出现报错, 说明安装完成.注意事项:• 安装软件时由于需要向系统⽬录中写⼊内容, ⼀般需要 sudo 或者切到 root 账⼾下才能完成.• yum/apt安装软件只能⼀个装完了再装另⼀个. 正在yum/apt安装⼀个软件的过程中, 如果再尝试⽤yum/apt安装另外⼀个软件, yum/apt会报错.安装一次任何人都可以使用3 卸载软件# Centossudo yum remove lrzsz# Ubuntusudo apt remove lrzsz注意事项关于 yum / apt 的所有操作必须保证主机(虚拟机)⽹络畅通可以通过 ping 指令验证ping www.baidu.com当天yum / apt也能离线安装4 安装源Cetnos 安装源路径ll /etc/yum.repos.d/total 16-rw-r--r-- 1 root root 676 Oct 8 20:47 CentOS-Base.repo # 标准源-rw-r--r-- 1 root root 230 Aug 27 10:31 epel.repo # 扩展源//安装扩展源方便使用sudo yum install -y epel-releaseUbuntu 安装源路径cat /etc/apt/sources.list # 标准源ll /etc/apt/sources.list.d/ # 扩展源# ubuntu 安装扩展源就结合未来具体场景ubuntu apt更换国内镜像源【文档参考】转载原文链接https://blog.csdn.net/x1131230123/article/details/134291339二.vim编辑器图示例2-1 Linux编辑器-vim使用vi/vim的区别简单点来说它们都是多模式编辑器不同的是vim是vi的升级版本它不仅兼容vi的所有指令⽽且还有⼀些新的特性在⾥⾯。例如语法加亮可视化操作不仅可以在终端运⾏也可以运⾏于x window、 mac os、 windows。2-2 vim的基本概念• 正常/普通/命令模式(Normal mode)控制屏幕光标的移动字符、字或⾏的删除移动复制某区段及进⼊Insert mode下或者到 lastline mode• 插⼊模式(Insert mode)只有在Insert mode下才可以做⽂字输⼊按ESC键可回到命令⾏模式。• 末⾏模式(last line mode)⽂件保存或退出也可以进⾏⽂件替换找字符串列出⾏号等操作。在命令模式下*shift:*即可进⼊该模式。要查看你的所有模式打开 vim底⾏模式直接输⼊:help vim-modes2-3基本操作进⼊vim,在系统提⽰符号输⼊vim及⽂件名称后就进⼊vim全屏幕编辑画⾯: vim test.c不过有⼀点要特别注意就是你进⼊vim之后是处于[正常模式]你要切换到[插⼊模式]才能够[正常模式]切换⾄[插⼊模式]输⼊⽂字。• 输⼊a进入插入模式从当前光标所在的位置的下一个位置开始输入文字• 输⼊i进入插入模式从当前光标所在的位置开始输入文字• 输⼊o进入插入模式插入新的一行从行首开始输入文字[插⼊模式]切换⾄[正常模式]• ⽬前处于[插⼊模式]就只能⼀直输⼊⽂字如果发现输错了字,想⽤光标键往回移动将该字删除可以先按⼀下「ESC」键转到[正常模式]再删除⽂字。当然也可以直接删除。• [shift ;], 其实就是输⼊[:]退出vim及保存⽂件,在[正常模式]下按⼀下「:」冒号键进⼊「Last line mode」,例如:• : w 保存当前⽂件• : wq (输⼊「wq」,存盘并退出vim)• : q! (输⼊q!,不存盘强制退出vim)2-4 vim正常模式命令集正常模式命令模式• 插⼊模式按「i」切换进⼊插⼊模式「insert mode」按“i”进⼊插⼊模式后是从光标当前位置开始输⼊⽂件按「a」进⼊插⼊模式后是从⽬前光标所在位置的下⼀个位置开始输⼊⽂字按「o」进⼊插⼊模式后是插⼊新的⼀⾏从⾏⾸开始输⼊⽂字。• 从插⼊模式切换为命令模式按「ESC」键。1移动光标vim可以直接⽤键盘上的光标来上下左右移动但正规的vim是⽤⼩写英⽂字⺟h、j、k、l分别控制光标左、下、上、右移⼀格按G移动到⽂章的最后按「 $ 」移动到光标所在⾏的“⾏尾”按「^」移动到光标所在⾏的“⾏⾸”按「w」光标跳到下个字的开头按「e」光标跳到下个字的字尾按「b」光标回到上个字的开头按「#l」光标移到该⾏的第#个位置如5l,56l按gg进⼊到⽂本开始按shiftg进⼊⽂本末端按「ctrl」「b」屏幕往“后”移动⼀⻚按「ctrl」「f」屏幕往“前”移动⼀⻚按「ctrl」「u」屏幕往“后”移动半⻚按「ctrl」「d」屏幕往“前”移动半⻚2 删除⽂字「x」每按⼀次删除光标所在位置的⼀个字符「#x」例如「6x」表⽰删除光标所在位置的“后⾯包含⾃⼰在内”6个字符「X」⼤写的X每按⼀次删除光标所在位置的“前⾯”⼀个字符「#X」例如「20X」表⽰删除光标所在位置的“前⾯”20个字符「dd」删除光标所在⾏「#dd」从光标所在⾏开始删除#⾏3复制文字「yw」将光标所在之处到字尾的字符复制到缓冲区中。「#yw」复制#个字到缓冲区「yy」复制光标所在⾏到缓冲区。「#yy」例如「6yy」表⽰拷⻉从光标所在的该⾏“往下数”6⾏⽂字。「p」将缓冲区内的字符贴到光标所在位置。注意所有与“y”有关的复制命令都必须与“p”配合才能完成复制与粘贴功能。•4替换操作「r」替换光标所在处的字符。「R」替换光标所到之处的字符直到按下「ESC」键为⽌。5撤销上⼀次操作常用「u」如果您误执⾏⼀个命令可以⻢上按下「u」回到上⼀个操作。按多次“u”可以执行多次回复「ctrl r」: 撤销的恢复一旦退出无法进行撤销但你只是保存没有进行q退出任然可以进行编辑6更改「cw」更改光标所在处的字到字尾处「c#w」例如「c3w」表⽰更改3个字7跳⾄指定的⾏「ctrl」「g」列出光标所在⾏的⾏号。「#G」例如「15G」表⽰移动光标⾄⽂章的第15⾏⾏⾸。8字母大小写转换shift~先按下 shift 键再按下波浪号 ~ 不要停往后遇到的所有小写字母将被转成大写所有大写字母将被转成小写。9查找单词shift3#选中单词n:进行逆向查找2-5 vim底行模式命令集注意在使⽤底⾏模式之前请记住先按「ESC」键确定您已经处于正常模式再按「」冒号即可进⼊底⾏模式。1 列出⾏号「set nu」: 输⼊「set nu」后会在⽂件中的每⼀⾏前⾯列出⾏号。2) 跳到⽂件中的某⼀⾏「#」:「#」号表⽰⼀个数字在冒号后输⼊⼀个数字再按回⻋键就会跳到该⾏了如输⼊数字15再回⻋就会跳到⽂章的第15⾏。(3) 查找字符「/关键字」: 先按「/」键再输⼊您想寻找的字符如果第⼀次找的关键字不是您想要的可以⼀直按「n」会往后寻找到您要的关键字为⽌。常用「?关键字」先按「?」键再输⼊您想寻找的字符如果第⼀次找的关键字不是您想要的可以⼀直按「n」会往前寻找到您要的关键字为⽌。(4) 保存⽂件「w」: 在冒号输⼊字⺟「w」就可以将⽂件保存起来如果要强制保存可以再w后面加一个强制保存w!(5) 离开vim「q」按「q」就是退出如果⽆法离开vim可以在「q」后跟⼀个「!」强制离开vim。「wq」⼀般建议离开时搭配「w」⼀起使⽤这样在退出的时候还可以保存⽂件。(常用6查看函数手册!man[选项][函数名](按q键退出手册.常用7批量化替换字符%s/printf/cout/g把文中所有 printf 替换成 coutg --global 表示全局的意思常用8多文件多屏操作如果想把 test.c 文件中的 10 行代码复制 test1.c 文件中该如何操作呢vs test1.c在 vim 中打开 test1.c 文件左右分屏再按ctrl ww组合键可以切换文件w 要按两下。9跑任何想跑的命令格式!命令! 表示底行执行 bash 命令举例vim小技巧1.srcn就可以回到你要指定的行数重新打开源文件的话2.字母就表示最近开始的这个以它为开头的命令行2-7 简单vim配置1配置⽂件的位置• 在⽬录 /etc/ 下⾯有个名为vimrc的⽂件这是系统中公共的vim配置⽂件对所有⽤⼾都有效。• ⽽在每个⽤⼾的主⽬录下都可以⾃⼰建⽴私有的配置⽂件命名为“.vimrc”。如/root⽬录下通常已经存在⼀个.vimrc⽂件,如果不存在则创建之。• 切换⽤⼾成为⾃⼰执⾏ su 进⼊⾃⼰的主⼯作⽬录,执⾏ cd ~• 打开⾃⼰⽬录下的.vimrc⽂件执⾏ vim .vimr2常⽤配置选项,⽤来测试•设置语法⾼亮: syntax on•显⽰⾏号:set nu 如果要取消的话再set前面加就可以了进行注释•设置缩进的空格数为4:set shiftwidt3使用插件要配置好看的 vim 原生的配置可能功能不全可以选择安装插件来完善配置保证用户是你要配置的用户。【参考文档】手把手教你把Vim改装成一个IDE编程环境(图文)_vimhttps://github.com/wsdjeg/vim-galore-zh_cn2-8 vim 中批量添加和删除注释方法一块选择模式(1批量添加注释进入 vim 编辑器按 ctrlv 进入块选择视图模式visual block然后移动光标选择要添加注释的行再按 shifti / I 键大写字母进入 Insert 插入模式输入你要插入的注释符比如 //。最后按 Esc 键你所选择的行就被注释上了2批量删除注释同样按 ctrlv 进入块选择视图)模式选中要删除的行首的注释符号注意 // 要选中两个。选好之后按 d 键即可删除注释Esc 保存退出。//方法二替换命令在底行模式下可以采用替换命令进行注释1添加注释起始行号, 结束行号 s/^/注释符/g表示在 xx 到 xx 行加入注释符^ 表示行首的意思然后按下回车键注释成功。2)删除注释起始行号, 结束行号 s/^注释符//g表示取消 xx 到 xx 行行首的注释符然后按)下回车键取消注释成功。举例说明三.gcc/g编辑器3-1gcc/g背景程序运行过程预处理进行宏替换--编译生成汇编--汇编生成机器可识别的代码--链接生成可执行文件/库文件3-2 gcc编译选项格式 gcc [选项] 要编译的⽂件 [选项] [⽬标⽂件]【补充选项】-E只激活预处理,这个不⽣成⽂件,你需要把它重定向到⼀个输出⽂件⾥⾯-S编译到汇编语⾔不进⾏汇编和链接-c编译到⽬标代码-o⽂件输出到 ⽂件-static 此选项对⽣成的⽂件采⽤静态链接-g ⽣成调试信息。GNU 调试器可利⽤该信息。-shared 此选项将尽量使⽤动态库所以⽣成⽂件⽐较⼩但是需要系统由动态库.-O0 -O1 -O2 -O3 编译器的优化选项的4个级别-O0表⽰没有优化,-O1为缺省值-O3优化级别最⾼-w 不⽣成任何警告信息。-Wall ⽣成所有警告信息备注记忆小技巧 esc,iso3-2-1 预处理(进⾏宏替换)• 预处理功能主要包括宏定义,⽂件包含,条件编译,去注释等。• 预处理指令是以#号开头的代码⾏。• 实例: gcc –E hello.c –o hello.i• 选项“-E”,该选项的作⽤是让 gcc 在预处理结束后停⽌编译过程。• 选项“-o”是指⽬标⽂件,“.i”⽂件为已经过预处理的C原始程序。3-2-2 编译⽣成汇编• 在这个阶段中,gcc ⾸先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的⼯作,在检查⽆误后,gcc 把代码翻译成汇编语⾔。• ⽤⼾可以使⽤“-S”选项来进⾏查看,该选项只进⾏编译⽽不进⾏汇编,⽣成汇编代码。• 实例: gcc –S hello.i –o hello.s3-2-3 汇编⽣成机器可识别代码• 汇编阶段是把编译阶段⽣成的“.s”⽂件转成⽬标⽂件• 读者在此可使⽤选项“-c”就可看到汇编代码已转化为“.o”的⼆进制⽬标代码了• 实例: gcc –c hello.s –o hello.o3-2-4 连接⽣成可执⾏⽂件或库⽂件• 在成功编译之后,就进⼊了链接阶段。• 实例: gcc hello.o –o hello3-3 动态链接和静态链接在我们的实际开发中不可能将所有代码放在⼀个源⽂件中所以会出现多个源⽂件⽽且多个源⽂件之间不是独⽴的⽽会存在多种依赖关系如⼀个源⽂件可能要调⽤另⼀个源⽂件中定义的函数但是每个源⽂件都是独⽴编译的即每个*.c⽂件会形成⼀个*.o⽂件为了满⾜前⾯说的依赖关系则需要将这些源⽂件产⽣的⽬标⽂件进⾏链接从⽽形成⼀个可以执⾏的程序。这个链接的过程就是静态链接静态链接的缺点很明显• 浪费空间因为每个可执⾏程序中对所有需要的⽬标⽂件都要有⼀份副本所以如果多个程序对同⼀个⽬标⽂件都有依赖如多个程序中都调⽤了printf()函数则这多个程序中都含有printf.o所以同⼀个⽬标⽂件都在内存存在多个副本• 更新⽐较困难因为每当库函数的代码修改了这个时候就需要重新进⾏编译链接形成可执⾏程序。但是静态链接的优点就是在可执⾏程序中已经具备了所有执⾏程序所需要的任何东西在执⾏的时候运⾏速度快。动态链接动态链接的出现解决了静态链接中提到问题。动态链接的基本思想是把程序按照模块拆分成各个相对独⽴部分在程序运⾏时才将它们链接在⼀起形成⼀个完整的程序⽽不是像静态链接⼀样把所有程序模块都链接成⼀个单独的可执⾏⽂件。动态链接其实远⽐静态链接要常⽤得多3-4 动态库和静态库• 我们的C程序中并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,⽽没有定义函数的实现,那么,是在哪⾥实“printf”函数的呢?• 答案是:系统把这些函数实现都被做到名为libc.so.6 的库⽂件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进⾏查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,⽽这也就是链接的作⽤.静态库是指编译链接时,把库⽂件的代码全部加⼊到可执⾏⽂件中,因此⽣成的⽂件⽐较⼤,但在运⾏时也就不再需要库⽂件了。其后缀名⼀般为“.a”动态库与之相反,在编译链接时并没有把库⽂件的代码加⼊到可执⾏⽂件中,⽽是在程序执⾏时由运⾏时链接⽂件加载库,这样可以节省系统的开销。动态库⼀般后缀名为“.so”,如前⾯所述的libc.so.6 就是动态库。gcc 在编译时默认使⽤动态库。完成了链接之后,gcc 就可以⽣成可执⾏⽂件,如下所⽰。 gcc hello.o –o hellogcc默认⽣成的⼆进制程序是动态链接的这点可以通过 file 命令验证。注意1• Linux下动态库XXX.so, 静态库XXX.a• Windows下动态库XXX.dll, 静态库XXX.lib⼀般我们的云服务器C/C的静态库并没有安装可以采⽤如下⽅法安装# Centosyum install glibc-static libstdc-static -y#ubuntu普通用户权限不可以得提高权限用sudo或者切换超级用户【问题补充】1.Linux 下生成的可执行程序默认是动态链接的如何查看呢1使用ldd [filename]命令可查看可执行文件的库依赖关系。2使用file [filename]命令可以查看可执行文件的信息和类型。2.想要生成的可执行程序是静态链接的该如何做呢输入指令gcc test.c -o test_s -static四.⾃动化构建-make/Makefile4-1 背景• ⼀个⼯程中的源⽂件不计数其按类型、功能、模块分别放在若⼲个⽬录中makefile定义了⼀系列的规则来指定哪些⽂件需要先编译哪些⽂件需要后编译哪些⽂件需要重新编译甚⾄于进⾏更复杂的功能操作• makefile带来的好处就是⸺“⾃动化编译”⼀旦写好只需要⼀个make命令整个⼯程完全⾃动编译极⼤的提⾼了软件开发的效率。•make是⼀个命令⼯具是⼀个解释makefile中指令的命令⼯具⼀般来说⼤多数的IDE都有这。•make是⼀条命令makefile是⼀个⽂件文件中保存的是目标文件和原始文件间的依赖关系和依赖方法两个搭配使⽤完成项⽬⾃动化构建。4-2基本使用假设我们创建了一个源文件myproc.c现在把他编译成可执行文件方法一直接使用gcc命令方法二使用make命令创建一个makefile的文件通过make的命令进行编译那如何创建makefiel呢那就要了解依赖关系和依赖方法进行学习依赖关系和依赖方法依赖关系就是我依赖于谁myproc.o 依赖myprocmyproc.o依赖myproc.s,myproc.s依赖于myproc.i,myproc.i依赖于myproc.c依赖方法对应的那个方法是如何生成我想要的结果编写makefie文件编写好之后会用make命令.PHONY的作用简化makefile当会出现多个文件的makefile这里的头文件可以不用放进来因为编译代码它可以自动展开bian把头文件的代码拷贝到源文件中所以找到头文件一般比较重要通过系统路径当前路径注意一般遇到的项目比较多时可以不用gcc命令进行可以用make/makefile进行自动化构建项目.PHONY解释关键字phony 本身不是修饰词而是 Makefile 里的一个特殊目标伪目标声明它的作用是告诉 make “别把我当成一个叫 phony 的文件也别去检查它的时间戳只要我被作为目标执行就无条件执行它下面的命令。”phony 本身不是修饰词而是 Makefile 里的一个特殊目标伪目标声明它的作用是告诉 make “别把我当成一个叫 phony 的文件也别去检查它的时间戳只要我被作为目标执行就无条件执行它下面的命令。”项⽬清理⼯程是需要被清理的像clean这种没有被第⼀个⽬标⽂件直接或间接关联那么它后⾯所定义的命令将不会被⾃动执⾏不过我们可以显⽰要make执⾏。即命令⸺“make clean”以此来清除所有的⽬标⽂件以便重编译。• 但是⼀般我们这种clean的⽬标⽂件我们将它设置为伪⽬标,⽤.PHONY 修饰,伪⽬标的特性是总是被执⾏的。什么叫做总是被执⾏总结.PHONY:让make忽略源⽂件和可执⾏⽬标⽂件的M时间对⽐4-3make的推导过程编译从上到下进行推导过程从下到上执行依赖方法make时如何工作的make是如何⼯作的,在默认的⽅式下也就是我们只输⼊make命令。那么1. make会在当前⽬录下找名字叫“Makefile”或“makefile”的⽂件。2. 如果找到它会找⽂件中的第⼀个⽬标⽂件target在上⾯的例⼦中他会找到 myproc 这个⽂件并把这个⽂件作为最终的⽬标⽂件。3. 如果 myproc ⽂件不存在或是 myproc 所依赖的后⾯的 myproc.o ⽂件的⽂件修改时间要⽐ myproc 这个⽂件新可以⽤ touch 测试那么他就会执⾏后⾯所定义的命令来⽣成myproc 这个⽂件。4. 如果 myproc 所依赖的 myproc.o ⽂件不存在那么 make 会在当前⽂件中找⽬标为myproc.o ⽂件的依赖性如果找到则再根据那⼀个规则⽣成 myproc.o ⽂件。这有点像⼀个堆栈的过程5. 当然你的C⽂件和H⽂件是存在的啦于是 make 会⽣成 myproc.o ⽂件然后再⽤myproc.o ⽂件声明 make 的终极任务也就是执⾏⽂件 hello 了。6. 这就是整个make的依赖性make会⼀层⼜⼀层地去找⽂件的依赖关系直到最终编译出第⼀个⽬标⽂件。7. 在找寻的过程中如果出现错误⽐如最后被依赖的⽂件找不到那么make就会直接退出并报错⽽对于所定义的命令的错误或是编译不成功make根本不理。8. make只管⽂件的依赖性即如果在我找了依赖关系之后冒号后⾯的⽂件还是不在那么对不起我就不⼯作啦。【补充】五. Linux第⼀个系统程序−进度条5-1.回⻋换⾏概念回车\r进行表示。即回到当前行的最开始的位置此时如果你进行数据的添加会不断覆盖你之前写过的数据.换行。回车换行就是光标移到下一行最开始位置补充;c语言当中就是\n表示回车换行键盘上就是enter进行回车换行5-2缓冲区的概念把下面的两个代码放进linux操作系统会发生啥#include stdio.h #include unistd.h//sleep() int main() { printf(hello bite!);//这里面没有\n sleep(3); return 0; }观察它的现象先休眠3秒结束接着打印出hello bite 结束程序#include stdio.h #include unistd.h//sleep() int main() { printf(hello bite!\n);//有\n sleep(3); return 0; }观察它的现象先打印出hello bite然后休眠3,结束程序当 sleep(3); 执行的时候printf(hello bite\n); 已经执行完了但却没有先打印字符串这是为什么呢printf(hello world); 已经执行完了但并不代表字符串就得显示出来。那在执行 sleep(3); 期间字符串在哪里呢\n缓冲区就是一段内存空间可以暂存临时数据在合适的时候刷新出去。【补充】刷新内存条为了不忘记数据必须每隔很短的时间比如64毫秒就把所有存储单元里的电信号重新读一遍、再写一遍。一般就是把数据真正写入磁盘文件显示器网络等设备或者文件当中。任何的c语言程序启动的时候需要的三个流在没有\n刷新的前提下可以通过这个函数进行强制刷新#include stdio.h #inlcude unistd.h int main() { printf(hello bite!); fflush(stdout);//刷新函数 强制刷新 sleep(3); return 0; }【解释现象】我们想要把字符串显示到显示器上显示器默认是行刷新遇到 \n 才刷新但是我们前面写的代码中并没有 \n所以 printf 执行完并没有刷新。\n为了在 printf 执行完的时候让字符串立马显示出来需要进行强制刷新把字符串尽快的写入显示器中。同时没有\n的时候可以通过这个函数进行强制刷新5-3展示进度条代码源文件process.c #include process.h//fflush #include string.h//memset #include unistd.h//usleep #define NUM 101//101个字符 换行符 #define STYLE // vesion1 void process_v1() { 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); } // verison2版本2) void FlushProcess(double total, double current) { char buffer[NUM]; memset(buffer, 0, sizeof(buffer)); const char *lable|/-\\; int len strlen(lable); static int cnt 0; // 不需要⾃⼰循环,填充# int num (int)(current*100/total); // 11.0 / 1000 int i 0; for(; i num; i) { buffer[i] STYLE; } double rate current/total; cnt % len; printf([%-100s][%.1f%%][%c]\r, buffer, rate*100, lable[cnt]); cnt; fflush(stdout); }头文件process.h #pragma once #include stdio.h void process_v1(); void FlushProcess(double total, double current);测试文件$ cat main.c #include process.h #include stdio.h #include unistd.h double total 1024.0; double speed 1.0; void DownLoad() { double current 0; while(current total) { FlushProcess(total, current); // 下载代码 usleep(3000); // 充当下载数据 current speed; } printf(\ndownload %.2lfMB Done\n, current); } int main() { DownLoad(); DownLoad(); DownLoad(); DownLoad(); DownLoad(); DownLoad(); DownLoad(); DownLoad(); return 0; }自动化编译展示结果显示5-4倒计时小程序#include stdio.h #include unistd.h int main() { int i 10; while(i 0) { printf(%-2d\r, i); // \n fflush(stdout); i--; sleep(1); } printf(\n); return 0; }现象倒计时计数从10到0进行覆盖计数【补充】在C语言中\r代表回车Carriage Return控制字符ASCII码是13(只回车回到行首覆盖写)【扩展】内存里的二进制到了屏幕上为什么变成了字符你有没有想过这样一个问题int count 123456;在内存里只占 4 个字节但用 printf 打印到屏幕上却显示成了 6 个字符原因很简单内存是给 CPU 看的显示器是给人看的。CPU 认识二进制0101...但人只认识字符1、2、3...。所以 printf的本质工作就是一次“翻译”——把内存里的 4 字节二进制整数转换成 6 个独立的字符再一个个发送到显示器上。反过来scanf 做的是逆向翻译把你敲下的 1 2 3 4 5 6 这 6 个字符重新拼回一个 4 字节的整数存进内存。这就解释了为什么键盘和显示器被统称为“字符设备”——它们只认字符不认二进制。也解释了为什么文本文件和二进制文件不一样文本文件存的是转换后的字符给人看的二进制文件存的是内存原样给机器读的。