湖南养老院中企动力网站建设,网站如何实现微,wordpress 热门用户,linux 部署wordpress目录
一、编译器——gcc/g的使用
gcc/g的安装
gcc的安装#xff1a;
g的安装#xff1a;
gcc/g的基本使用
gcc的使用
g的使用
动态链接与静态链接
程序的翻译过程
1. 一个C/C程序的构建过程#xff0c;程序从源代码到可执行文件必须经历四个阶段
2. 理解选项的含…目录
一、编译器——gcc/g的使用
gcc/g的安装
gcc的安装
g的安装
gcc/g的基本使用
gcc的使用
g的使用
动态链接与静态链接
程序的翻译过程
1. 一个C/C程序的构建过程程序从源代码到可执行文件必须经历四个阶段
2. 理解选项的含义
第一步预处理
第二步编译
第三步汇编
第四步链接
动静态链接的认识
验证我们所写的程序是动态链接还是静态链接
file 可执行文件
ldd 指令
静态库的安装
C语言安装静态库
C安装静态库
静态链接
二、项目自动化构建工具——make/Makefile
make与Makefile的概念
Makefile的原理
Makefile的语法
依赖关系和依赖方法
项目清理
如何理解 .PHONY 修饰的是一个伪目标
我们可以知道被.PHONY修饰的对象总可以被执行
gcc 如何得知 mytest 是最新呢
如何证明 gcc 根据修改的时间得知 mytest 是最新
Makefile的推导规则
三、版本控制器——git
git 是什么
git 的操作
1. 进入gitte官网先新建一个仓库
2、Linux中提交代码操作
1. git clone拉取远端仓库克隆到本地(目录克隆到本地)
2. git add . 把需要提交的目录(项目)复制或剪切到本地仓库
3. git commit -m ‘提交日志’ 修改之后的代码添加进去提交本地库
4. git push 推送到远程仓库这才是把本地仓库的代码推送至远程仓库
5. 如果在远端我们的代码修改了git status 查看 git 的状态
6. git log 查看提交历史记录
四、调试器——gdb
调试之前我们先创建文件以及准备调试代码
test.c 文件
编译成debug版本
gdb 的使用
gdb的安装
编辑
基本使用
① l 查看代码
② b 打断点、info查看断点、d 删除断点
③ r 开始调试调试起来
④ n 逐过程、s 逐语句
⑤ c 运行到下一个断点处
⑥ bt 查看调用堆栈
⑦ finish 运行完当前函数
⑧ p 查看变量值
⑨ display 常显示变量的值、undisplay取消常显示
⑩ until 跳出循环
⑪ info locals 查看特定区域的临时变量
五、Linux小程序——进度条的实现
基本概念
fflush的使用
回车换行的理解
倒计时程序的实现
进度条的实现
process.h
process.c
main.c
Makefile 一、编译器——gcc/g的使用
gcc/g的安装
gcc的安装
yum install -y gcc
g的安装
yum install -y gcc-c libstdc-devel
gcc/g的基本使用 我们在使用 gcc/g 进行编译的时候一般都带选项: -o 在 gcc -o test test.c 这个命令中gcc编译器会对test.c这个源文件进行编译和链接操作。正常情况下如果没有-o选项gcc会生成一个默认名称的可执行文件在 Linux 等系统下通常是a.out。 但是当使用-o test时编译器会将生成的可执行文件命名为test而不是默认的a.out。 注意gcc -o test test.c 和 gcc test.c -o test 这两种写法都是正确的。在这两种情况下gcc编译器都能够理解-o test是要将编译生成的可执行文件命名为test而test.c是要编译的源文件。 gcc的使用 g的使用 动态链接与静态链接 我们在学习动态链接与静态链接的时候需要对程序的翻译过程进行复习一下这都是我们C语言阶段就学习过的内容。 程序的翻译过程
1. 一个C/C程序的构建过程程序从源代码到可执行文件必须经历四个阶段
预处理头文件的展开、宏替换、条件编译、去掉注释 编译检查语法错误将预处理后的源代码生成为汇编代码 汇编汇编代码转换成二进制的机器码 链接多个目标文件的文件链接成一个可执行文件
2. 理解选项的含义 当生成了一个可执行文件但是我们并不想让他直接编译完成编译的过程是一下就走完了而接下来我们想看他的过程就在编译的时候带上选项就可以查看每一个阶段的过程。 注意C同样是这种过程。 在测试之前我们重新在 test.c 中编写一个用于测试的代码
#include stdio.h
#define N 20
int main()
{ //测试去掉注释 printf(hello wolrd 1\n); //printf(hello wolrd 2\n); //printf(hello wolrd 3\n); //printf(hello wolrd 4\n); //printf(hello wolrd 5\n); //printf(hello wolrd 6\n); //printf(hello wolrd 7\n); //printf(hello wolrd 8\n); //printf(hello wolrd 9\n); //printf(hello wolrd 10\n); //测试条件编译
#ifdef CONDITION printf(condition\n);
#else printf(no condition\n);
#endif //测试宏替换 printf(宏%d\n, N); return 0;
}
第一步预处理 选项 -E 从现在开始进行程序的翻译当你将预处理做完就停下来。 如果去掉 –o 预处理这么多内容打印到显示器上特别不好看选项 -o: 指明形成的临时文件名称 .i 使用 .i 作为预处理文件的扩展名是一种比较常见的约定就像c语言文件名后缀是 .c一样。 观察下面的代码我们可以看到多了800多行代码这就是头文件的展开把库中的代码拷贝过来了。 然后就进行了宏替换预处理阶段就已经做了的。 最后只剩hello world 1这就是去掉注释。 条件编译这里把这个没有的也裁掉了这就是条件编译。 注意我们要用的头文件、必须在C语言库中存在平时在某个平台写代码的时候头文件必须在该系统中存在 , Linux中库头文件在 /usr/include/stdio.h 目录下,平时我们安装VS2022同时也会把头文件库文件安装到v2022所对应的目录下这也就是我们为什么写代码可以自动补齐的原因。 gcc -E test.c -o test.i我们不定义CONDITION也可以通过传参来定义 第二步编译 编译把c语言代码变成汇编代码。 选项 -S从现在开始进行程序的翻译做完编译工作变成汇编之后就停下来。 编译之后Linux下通常以 .s后缀结尾作为存储汇编代码的文件 gcc -S test.i -o test.s第三步汇编 汇编语言不能被计算机直接执行把汇编变成二进制目标文件 选项 -c将汇编代码转成二进制目标文件就停下来没有进行链接。 vim test.o 进入该文件我们看不懂但是可以 od test.o进行阅读该二进制文件。 test.o虽然是二进制文件但是不能被执行我们可以加上权限发现还是不能被执行原因在于少了一步链接这三个步骤只在编译你写的代码比如你在c语言上的printf的函数是你写吗你只是调用了printfprintf的实现你没有写。 gcc -c test.s -o test.o我们执行该目标文件发现不能被执行原因是因为缺少一步链接 第四步链接 我们把前面三个步骤完成之后就可以进行链接操作了链接是将多个目标文件以及所需的库文件整合在一起的关键过程。 把你写的代码和 C标准库中的代码合起来这就是链接的过程可以不带任何选项 gcc test.o –o mytest 链接就形成了可执行程序形成可执行的二进制程序(库你的代码)。 gcc test.o -o mytest 动静态链接的认识 我们要明白自己编写的代码与库中的代码是不同的。像 C 标准库是他人事先准备好以供我们直接使用的。比如我们在代码里写了像printf这类库函数的调用语句实际上我们只是进行了调用并没有去实现这些函数。只有在进行链接这一环节时库函数对应的具体实现才会和我们写的代码关联起来。 而链接的本质核心就是解决我们调用库函数时如何与标准库或其他相关库建立关联的问题这其中就涉及到选择动态链接还是静态链接的方式。动态链接是在程序运行时按需加载共享库来获取函数实现而静态链接则是在链接阶段直接把库函数的代码复制到可执行文件当中。 动态链接 优点 资源节省可执行程序体积小因为不包含库代码运行时才加载共享库节省内存、磁盘和网络资源。例如多个程序共享动态库内存实例。更新方便库更新时只要接口兼容程序无需重新编译就能使用新功能。缺点 运行依赖依赖外部环境缺少库或版本不匹配时程序无法运行。性能损耗启动要加载库运行中调用库函数有系统开销影响性能和启动速度。静态链接 优点 独立稳定不依赖外部库库升级、删除或移动不影响程序运行程序有很好的稳定性。行为可预测运行行为由自身代码决定便于在不同环境部署和调试。缺点 资源占用可执行程序体积大占用更多磁盘和内存空间多个程序用相同静态库会有代码冗余。更新不便库更新时程序要重新编译才能使用新功能大型项目中耗时耗资源。 动静态库可以类比成摄影爱好者与照片滤镜库
假设你是一个摄影爱好者你有一部相机相当于程序本身你平时会拍摄各种各样的照片程序执行各种任务。
动态库的情况
现在有一个非常流行的在线照片滤镜应用相当于动态库。当你拍完照片后你想要给照片添加一些特殊的滤镜效果但是你的相机本身没有这些滤镜功能就像程序本身没有这个功能的实现。
你打开相机中的一个连接功能相当于程序中的函数调用接口连接到这个在线滤镜应用。每次你想要使用一个滤镜的时候相机就会通过网络相当于运行时环境向这个在线滤镜应用发送照片和滤镜请求就像程序运行时请求动态库中的功能这就是动态链接。这个在线滤镜应用会处理你的照片添加滤镜后再把处理后的照片发送回你的相机就像动态库提供功能实现并返回结果。
很多摄影爱好者都可以使用这个在线滤镜应用多个程序共享动态库。而且如果这个滤镜应用更新了新的滤镜效果或者优化了滤镜算法动态库更新只要相机和滤镜应用之间的连接方式接口不变你的相机依然可以使用这些新功能来处理照片。
静态库的情况
后来你发现每次连接到在线滤镜应用很麻烦而且有时候网络不好就没办法使用滤镜。于是你购买了一个带有大量滤镜功能的存储卡相当于静态库这个存储卡可以插入你的相机。
当你把存储卡插入相机后相机就把存储卡里的滤镜功能就像静态库中的代码复制到了相机内部的可用功能列表中就像静态链接把库代码复制到可执行文件这就是静态链接。现在你拍摄完照片后想要添加滤镜相机就可以直接使用存储卡里已经复制过来的滤镜功能来处理照片不需要再连接到外部的在线滤镜应用不依赖外部库运行。即使这个在线滤镜应用因为某些原因停止服务比如公司倒闭等情况就像动态库不可用你依然可以在相机里使用这些滤镜功能来处理照片。
验证我们所写的程序是动态链接还是静态链接
file 可执行文件 ldd 指令 ldd 可执行文件 用于查看程序可执行文件或共享库依赖的动态共享库的工具。当你运行ldd命令并跟上一个可执行文件的名称时它会显示该可执行文件在运行时需要加载的动态库的路径和名称等相关信息。 静态库的安装 默认情况下都是动态链接的如果我们想要静态链接需要怎么办呢 ls /lib64/libc.a 不一定存在静态库静态库不存在需要自己安装。 C语言安装静态库
yum install -y glibc-staticC安装静态库
yum install -y libstdc-static静态链接 在系统中C 动态库也称为共享库是被多个使用该库的程序所共享的。尽管使用 C 动态库的程序众多但通常系统中只存在一份该动态库的物理副本。这体现了动态库的共享特性即多个程序在运行时可以同时访问并使用这同一个动态库避免了库代码在内存中的重复存储从而节省了系统的内存资源。例如标准 C 库如libc.so被众多的 C 语言程序所依赖在系统运行时这些程序通过动态链接的方式引用libc.so而无需各自拥有一份独立的libc.so代码副本。 静态链接并不是拷贝动态库内部的代码。静态链接是在程序编译阶段将所需的库代码通常是静态库以.a结尾直接复制到可执行文件中使其成为可执行文件的一部分从而在运行时不再依赖外部的库包括动态库。所以静态链接与动态库的机制是相互独立的静态链接不会直接操作动态库的代码。 Windows动静态链接的原理是一样的动态库通常以.dll为后缀静态库一般是以.lib为后缀 我们也可以用C进行静态链接 二、项目自动化构建工具——make/Makefile
make与Makefile的概念 make 是一个命令Makefile是一个文件。 make与Makefile存在的意义 Makefile 所带来的好处集中体现在自动化编译方面。这并不意味着完全无需人工干预而是在初始阶段开发人员需要根据项目的结构和需求编写 Makefile 文件精心规划好源文件与目标文件的依赖关系以及相应的编译规则。一旦 Makefile 文件编写完成后续使用 Make 命令时它会自动读取 Makefile 中的内容按照既定的规则和依赖关系有条不紊地对程序或项目进行编译无需开发人员再次手动调整编译过程。这使得在项目开发过程中无论是对单个源文件进行修改后重新编译还是对整个项目进行全新构建都能够通过简单地执行 Make 命令快速、准确地完成从而实现了高效、稳定的自动化构建过程为软件开发的迭代和维护提供了有力支持。 注意 Makefile的 m 可以大写也可以小写。 我们可以来使用一下Makefile下面会说明Makefile
就是不用再手写gcc了直接make就可以了看起有点弱其实慢慢就会发现这个Makefile很强 Makefile的原理 Makefile 必须包含依赖关系和依赖方法这两个关键要素其存在意义在于为构建项目提供自动化支持使项目能够依据文件间的依赖关系和生成方法有条不紊地完成编译、链接等构建流程避免手动操作的繁琐与易错性高效达成项目构建这一目标。 Makefile 的运行就如同生活中的一个场景。比如当你打电话说 “爸我是你儿子”此时这仅仅建立了一种依赖关系即你依赖于自己的父亲但仅凭这一句父亲并不清楚你到底想要做什么事情自然无法推进这是因为缺少依赖方法。再比如你不可能去找室友的爸爸借钱原因是你和室友的爸爸之间不存在任何依赖关系。只有当你既明确了依赖关系像打电话跟自己的爸爸表明身份又清晰地阐述依赖方法例如接着说 “我没钱吃饭了给我打点钱吧”这样依赖于父亲打钱这件事情才能够完成。在 Makefile 中也是如此只有同时具备依赖关系和依赖方法这两个关键要素项目构建这件事情才能够顺利实现。 Makefile的语法
依赖关系和依赖方法 第一行整体我们称为依赖关系。 mytest : test.c 目标文件可执行程序/临时文件 : 依赖文件列表, 这里只有一个依赖文件 这里表示 mytest 依赖于test.c 第二行整体我们称为依赖方法 写完了Makefile我们make一下就会生成可执行文件然后运行该文件就可以了 项目清理 随着项目的不断编译和构建会产生许多可执行程序以及一些诸如目标文件.o文件、中间编译文件等临时文件。有时候我们可能想要重新编译整个项目或者不想保留这些已生成的可执行程序和临时文件了比如它们占用了过多磁盘空间或者之前的编译结果出现了一些未知问题想要重新开始等情况这时候就需要一种方法来清理它们。 如何清理 vim Makefile 进入Makefile之后接着往下输入 clean 这里可以为空(依赖关系可以为空也就说clean不依赖与任何文件) 在下来 tab 开头的就是依赖方法 我们再用 .PHONY 修改 clean 红色为伪目标 .PHONY 修饰的是一个伪目标 为什么make 和 make mytest 也是可以而 clean 要 make clean 第一个遇到的可以省略名称仅此而已默认情况下只形成一个目标文件(可执行目标文件)不指名默认就是第一个。 如何理解 .PHONY 修饰的是一个伪目标 当我们不断 make 的时候会发现不让你编译了因为是最新的没有修改没必要重新编译 可是当我们再不断调用 make clean 的时候总是能执行 rm –f mytest 我们可以知道被.PHONY修饰的对象总可以被执行 但是我们一般不会这样做将我们生成的可执行程序用.PHONY修饰, 但是这都不是重要的 最重要的是 gcc 如何得知 mytest 是最新呢 我们再改回原来的Makefile gcc 如何得知 mytest 是最新呢 肯定跟时间有关系在我们学习指令的时候就接触过一个指令 statstat命令是一个用于查看文件或文件系统状态信息的工具。 Access访问时间这是文件最后一次被访问如查看内容的时间。 Modify修改时间记录文件内容最后一次修改的时间。 Change改变时间是文件元数据属性如权限、所有者等最后一次改变的时间。 为什么change会随着modify的改变而改变呢 当我修改了文件内容modify修改了change也会随着修改因为文件的大小变化了也意味着文件的属性也跟着变化所以change会改变。 Change 和 Modify 的时间变化能够理解但是为什么Access是指我们cat访问/vim查看该文件的时间为什么没有任何的变化 访问文件不一定改内容改内容一定访问如果每次访问都修改时间导致Access修改的频率太多了就需要在磁盘进行多次的 IO输入 / 输出操作别人设置文件让别人阅读就不在过于关心访问时间如果别人修改了文件时间立马更新Modify时间所以操作系统采用的是你访问次数达到多少次就更新一次Access的时间这种策略没有什么规律我们主要关注 Change 和 Modify。 我们现在知道了这么多时间但是和 gcc 有什么关系 它怎么知道我们文件是最新的 先有源文件 test.c再有可执行程序 mytest test.c 的 Modify 的时间 一定比 mytest 的 Modify 的时间要更早 如果 test.c 里面有bug改了一下里面的内容然后就会更新源文件test.c 的 Modify的时间这个时候test.c 里面的时间就是新的比 mytest 的时间新了就是比较两个时间的新旧。 如何证明 gcc 根据修改的时间得知 mytest 是最新 我们知道一个指令touch除了创建文件还可以修改时间 touch 可以更新文件的时间 综上所述凡是用.PHONY修饰的就是不要拿时间作对比了你每次都执行一下不要遵守时间对比的规则每次都要执行依赖方法而没有使用 .PHONY修饰的就是对比源文件的时间和可执行的时间变化来确定是不是需要进行编译。
Makefile的推导规则 程序的翻译过程从预处理、编译、汇编、链接 文件从 test.i - test.s - test.o 我们的可执行文件 mytest 依赖于 test.o 而 test.o 依赖于 test.s 而 test.s 依赖于test.i 我们在日常写Makefile中我们直接一步到位直接写依赖于源文件就可以了。 三、版本控制器——git 今天就让我们一起来学习一下个人使用 git 提交代码的基本操作流程吧后续更复杂的冲突处理、分支协作等内容我们可以再逐步深入学习。 git 是什么 git 就像是一个超级智能的代码 “时光机”。假设你在写代码就好像在创作一幅复杂的画作。每次你对代码进行修改无论是添加新功能、修复小错误还是优化性能git 都能帮你记录下这个 “画作”代码的不同状态。 比如说你写一个 C 程序最开始只有一个简单的打印 “Hello, World!” 的功能这是你代码的最初版本git 就像一个相册把这个初始版本保存了下来。之后你添加了一个计算两个数字相加的函数git 又会把这个有新功能的版本记录下来就好像在相册里新增了一张带有新内容的照片你还可以找到原来记录下的版本(可以回顾不同的版本)。 git 的操作
1. 进入gitte官网先新建一个仓库 gitte官网Gitee - 基于 Git 的代码托管和研发协作平台 进入官网之后我们先创建一个仓库 初始化仓库设置仓库模板选择分支我们先这样进行创建后续需要深入学习git 远端就会形成一个这个仓库 2、Linux中提交代码操作
git 的安装
sudo yum install -y git
准备我们要提交的代码文件 1. git clone拉取远端仓库克隆到本地(目录克隆到本地) 我们暂时先使用HTPS因为比较简单如果用SSH还需要进行配置 先复制好然后进入Linux指令行中输入 git clone 粘贴刚刚复制的内容 git clone:把远端仓库克隆到本地 当我们克隆到本地的时候有时候可能需要输入自己gitee的账号和密码 Linux中进入该仓库而远端隐藏了.git文件 注意点 当我们首次安装好了git之后系统会提示你进行配置 用户名 和 邮箱
要将码云Gitee的仓库与 Linux 系统关联起来
配置 Git 用户名和邮箱(如果还没配置的话)---我们在提交的过程中会出现提示
git config --global user.name 你的gitte用户名git config --global user.email 你的邮箱
2. git add . 把需要提交的目录(项目)复制或剪切到本地仓库 git add . 相当于添加到临时仓库(还没提交到本地库)相当于一个 准备区 3. git commit -m ‘提交日志’ 修改之后的代码添加进去提交本地库 git commit -m ‘提交日志信息’ 这个日志必须写也不要乱写。 这才是提交到了本地仓库 但是远端仓库还没没有提交所以我们需要推送到远端仓库 4. git push 推送到远程仓库这才是把本地仓库的代码推送至远程仓库 我们查看远端仓库发现多了一个我们提交的文件 5. 如果在远端我们的代码修改了git status 查看 git 的状态 如果远程库和本地库没有同步的话我们就 git pull 先把远端的拉到本地同步一下然后再进行 push pull 的本质就是强制我们每一个人必须和远端仓库保持一致不一致了就pull一下。 git pull 同步远程仓库本地库与远程仓库保持一致 如果你本地要删除这个文件都在前面加上 git 6. git log 查看提交历史记录 四、调试器——gdb 在调试思路上无论是在 Windows 还是 Linux 系统下目的都是为了找出代码中的错误。都需要关注变量的初始化、赋值、变化过程检查函数的参数传递是否正确、函数内部逻辑是否正确以及循环结构是否按照预期执行如循环次数是否正确、循环体中的逻辑是否正确等。比如在检查一个计算数组元素总和的函数时都需要考虑是否正确地遍历了数组是否正确地累加了元素的值思路都是从程序的输入、中间处理过程到输出逐步验证代码的正确性。 调试之前我们先创建文件以及准备调试代码
test.c 文件
#include stdio.h// 函数用于统计给定范围内能被divisor整除的数的个数及它们的和
void countAndSum(int start, int end, int divisor, int *count, int *sum) {*count 0;*sum 0;int i 0;for (i start; i end; i) { // 这里循环条件有错误少包含了边界值end应该是i end导致可能少统计一些数if (i % divisor 0) {(*count);*sum i;}}
}int main() { int start 1; int end 18;int divisor 3; int count; int sum; countAndSum(start, end, divisor, count, sum); printf(在 %d 到 %d 范围内能被 %d 整除的数有 %d 个它们的和是 %d\n, start, end, divisor, count, sum); return 0;
} 编译成debug版本 在学习C语言的时候我们就知道编译存在两种版本一种是release发布版目的主要用于向用户发布最终产品另一种是debug调试版目的专为开发人员在开发和调试阶段使用。 要用 gdb 调试变成debug版本才可以调试首先要进行给编译条件添加 -g表示生成debug 版本 gdb 的使用
我们要调试直接 gdb 可执行程序发现我们还没有gdb所以需要安装 gdb的安装
sudo yum install -y gdb基本使用
① l 查看代码 l 的全称是 list l 0 从0行显示想再往后显示不需要输指令了直接回车可以继续往下显示代码。 ② b 打断点、info查看断点、d 删除断点 打断点b 全称 breakPoint b 20 b 23都是打断点 查看断点 info b 去掉断点d 全称 deletePoint d 24这样删除不了断点删除是删除断点编号添加断点之后就有了断点编号。 ③ r 开始调试调试起来 r 程序跑起来在断点处停下来r 全称run r 相当于 Visual Studio下的 F5开始调试VS 下 F5开始调试有断点就在断点处停下来没有断点就直接跑完了到另外一个断点还是F5。 ④ n 逐过程、s 逐语句 启动调试之后下一步就可以逐过程 F10这里是 n 全称next 一行一行往下走 想进入这个函数逐语句 F11这里是 s 全称 step可以进入某个函数 ⑤ c 运行到下一个断点处 c 全称continue运行到下一个断点 可以一直c运行到下一个断点处 ⑥ bt 查看调用堆栈 s进去一个函数后 bt 查看函数的调用堆栈出了函数后还可以继续查看调用堆栈 ⑦ finish 运行完当前函数 通过这个finish可以确定这个函数是否存在错误 ⑧ p 查看变量值 p 只能临时查看我们要边看边调试变量的值。 ⑨ display 常显示变量的值、undisplay取消常显示 常显示可以显示变量值和地址也可以取消变量值和地址但是取消的时候也是取消编号。 取消常显示 ⑩ until 跳出循环 如果问题不在循环里面我们要跳出这个循环直接until然后继续 n 往下走 ⑪ info locals 查看特定区域的临时变量 五、Linux小程序——进度条的实现
基本概念
fflush的使用 这个代码会先出现 hello world然后休眠 2 秒。 如果我们去掉\n就没有打印内容两秒之后内容才打印出来这里先执行的是printf然后执行的是sleep因为我们的代码是顺序结构。 先执行printf不等于数据先显示printf已经执行完了只不过数据在缓冲区里面没有显示出来 缓冲区我们不知道是什么我们目前只需要知道它是一块内存就够了如果我们想要这个内容刷新出来可以使用 fflush(stdout)。 而 \n 刷新的是行缓冲。 fflush(stdout)刷新缓冲区 回车换行的理解 有一组概念回车换行回车换行是两个概念回车是回到当前行的开始换行是换到下一行 \r 回车 \n 换行 \r\n 回车换行 注意语言层面 \n 就是回车换行 倒计时程序的实现 有了这两个基础铺垫我们就可以完成一个简单的倒计时了。 反斜杠n就是回车换行我们不能使用回车换行我们就用反斜杠 r fflush(stdout)刷新缓冲区 进度条的实现 有了这些基础之后我们实现这个进度条就很容易上手了。 进度条一定是循环的头文件不需要在Makefile中写因为会在源文件中展开。 注意点\是C语言中的特殊字符如果我们要显示 \ 就需要\\ 模上4之后范围就在0-3 我们先把文件建立好写好之后先简单的测试一下Makefile是否正确 process.h
#pragma once
#include stdio.h
#include unistd.h
#include string.h
#define NUM 101
//#define STYLE #
#define S_NUM 5
//函数的声明
extern void ProcessOn();
process.c #include process.h //函数的实现void ProcessOn(){int cnt 0;//字符数组char bar[NUM];//进度条样式 char STYLE[S_NUM] {,#,,*,};//初始化bar memset(bar,\0,sizeof(bar));//旋转光标 const char* lable |/-\\;while(cnt 100) { //控制格式 printf([%-100s][%d%%][%c]\r,bar,cnt,lable[cnt%4]);fflush(stdout);
E bar[cnt] STYLE[N]; usleep(50000); //1秒 10000毫秒,3秒跑完} printf(\n); }
main.c
#include process.h
int main()
{ ProcessOn(); return 0;
}
Makefile
ProcessOn:main.c process.c gcc main.c process.c -o ProcessOn -DN1 #-D定义宏
.PHONY:clean
clean: rm -rf ProcessOn