💭 前言
本章我们先对缓冲区的概念进行一个详细的探究,之后会带着大家一步步去编写一个简陋的 "进度条" 小程序。最后我们来介绍一下 Git,着重讲解一下 Git 三板斧,一般只要掌握三板斧就基本够用了。
缓冲区(Buffer)
先说一下 unistd.h 库中的 sleep 函数,它可以按照秒去休眠
我们先创建一个文件,并写一些代码:
#include <stdio.h>#include <unistd.h> int main(void) { printf("Helo,World!/n"); sleep(2); return 0;}
??这里是先运行printf还是sleep???
这还用思考?肯定打出 Helo, World,先运行 处代码,然后运行 B 处代码休眠%20:
%20如果说:我们把/n给删了呢?
这里是休眠了2s后,才出现的hello world。怎么说???
看样子是先执行 B 再执行 了,but……
%20然而实际上,无论你加不加%20/n,代码都是从上往下先运行的,即先执行%20printf%20再执行%20sleep!
%20代码没有任何的循环判断跳转什么的操作,那一定是%20从上到下按顺序执行的,要坚信自己!
%20这就是所谓的%20"顺序结构",也是我们的默认结构。
%20既然是从上到下按顺序执行,可是我们运行代码观察到的现象就是%20sleep%20先休眠 然后打印啊。
%20真像:实际上,printf%20已经先执行了,只是这个%20"Helo,World"%20没有立马被显示出来罢了!
%20当我们%20sleep%20时也没有显示,当我们%20sleep%20完甚至到程序退出后,这个%20"Helo,World"%20才显示出来。
%20这个时候如果打印的消息如果没有立即被显示出来,
%20在%20sleep%20执行期间它最后显示出来证明了它的存在,
%20但是%20sleep%202s%20内它并没有显示出来,那么问题来了%20——%20这个%20"Helo,World"%20在哪?
%20没错,这就是就是 "%20缓冲区%20"%20!
对缓冲区的理解
%20什么是缓冲区?这个缓冲区在哪里?缓冲区其实说白了,就是一段内存空间。
%20既然是内存空间,那我们就能理解刚才举的例子里的%20"Helo,World"%20数据是放在了内存空间里。
%20只要在内存里就没有打印出来,所以我们%20sleep%202s%20时它一直在内存里%20"躺平"%20呢。
%20最后%20return%20退出的时候,这个数据才显示出来,所以才看到了我们刚才看到的现象
%20%20缓冲区的理解:就是一段内存空间。立马将内存中的空间显示出来 →刷新策略
%20我们今天不探讨什么策略,就往显示器打印这个点来说,我们只关注一种策略%20——%20行刷新 !
%20所谓的行刷新,就是你要输出的一个行字符串当中,看它是不是一个完整行,
%20如果是一个完整行,就会立马刷新出来;如果不是,就不刷新,让它去缓冲区一边凉快去,
%20等缓冲区变满了或者程序退出了,再或者碰到换行服务,再把它一块送出去。
%20%20那么,如何证明你一个文本是完整的一行呢?
%20这也很简单,只要你打印的内容包含%20/n,包含反斜杠%20n%20在内的之前的所有内容成为一行。
%20不是直接把数据刷到我们外设上,%20还是把数据先放到缓冲区里,只不过因为你有%20/n,
%20它就立马根据刷新策略,把内容给你刷新出来,仅此而已。
%20如果我不想用%20/n,我就想让我的数据立马刷新出去(立马显示出来)呢?
%20这里就说来话长了,我们不得不说一下%20stdin、stdout%20和%20stderr%20的知识。
%20一般一个程序默认在启动的时候会默认打开三个输入输出流:
%20#include%20<stdio.h>%20extern%20FILE*%20stdin;extern%20FILE*%20stdout;extern%20FILE*%20stderr;
%20如何刷新呢?我们还可以通过%20fflush()%20去强制刷新:
%20#include%20<stdio.h>%20int%20fflush(FILE*%20stream);
%20如果你仔细观察你会发现它的参数和我们%20stdin、stdout%20和%20stderr%20类型是一样的,都是%20FILE*
%20在没有%20/n%20时,我们通过%20fflush%20让它打印完立马给我刷新:
%20运行结果如下:
此时的Hello world!是立刻就显示出来了。
实现一个简易 "进度条"
在实现简易 "进度条" 之前,我们还需要讲解一下回车和换行的概念。
思考:你认为回车和换行是一个概念吗?
- 回车:将光标拨回到当前行的最开始(最左侧)
- 换行:新起一行(并不影响光标的位置)
我们所理解的 "换行" 并不是这里的换行,想达到我们所理解的 "换行" 效果,
即新起一行并将光标拨回最开始位置,就需要:
先模拟 "倒计时"
代码演示:从 9 开始倒计时
运行结果:
由9一直倒数
开始实现简易进度条
我们先创建一个空文件夹,并创建一个 process.c 文件:
然后我们形成一个 Makefile 文件:
然后我们打开刚才创建的 process.c 文件,我们实现出 '#' 的填充部分:
定义一个 process() 函数,用于实现进度条。我们假设 100 个单位,定义一个宏 TIMES 表示,然后创建 bar 数组存放,因为最后要存 /0 所以这里我们需要多预留一个位置给它,所以定义一个 TIMES+1 的宏,名曰 NUM。为了方便,我们索性使用 memset 将所有缓冲区空间设置为 /0。
然后开始我们的计数操作,创建一个 cnt 变量 while 它个 100 下,每次打印 bar 中的 1 个,然后用 # 填充 cnt 对应位置的 bar 元素。
运行结果如下:
emm,现在显然有两个问题亟待解决:
- sleep 一秒,这是打印地是否有些太慢……
- 这个进度条是否有些奇葩,哪有换行打的进度条雾草,太摩登了
我们先来解决第一个问题,看看 usleep 函数
按照微秒为单位去休眠,我们 usleep(20000) ,能让它 2 秒内跑完。
20000μs=20ms=0.02s
然后我们刚才还讲解缓冲区概念,的时候还介绍了 fflush() 和 /r,在这里就派上用场了。
和刚才的倒计时一样,这里换行的主要原因还是我们 printf 用了 /n,我们修改一下写的代码:
运行结果如下:
不错,有个进度条的样子了。但好像没有给进度条预留一块空间啊,
现在的进度条是带着 [ ] 直接往后怼的,我们可以给 [ ] 预留 100 个 字符空间:
printf("[%100s]/r", bar);
虽然给 [ ] 预留空间了,但是是从右往左反过来打的。
为什么会这样呢?因为 C 语言默认的对齐方式是右对齐的,如果想让它左对齐,就要加 -
printf("[%-100s]/r", bar);
下面我们来加上 "百分比"
百分比不就是我们定义的 cnt 变量么?我们打印出来就行:
printf("[%-100s] [%d %%]/r", bar, cnt);
最后,我们再实现一下 "不断旋转的光标",就大功告成了。
想做到不断旋转的视觉效果,通过 | / - / 这四个符号不断变化即可。
由于 / 需要用转义才能表示,所以需要 // ,我们把它们存到变量中。
打印时,访问我们定义的变量即可,这里将 cnt % 4 就可以按顺序循环访问这四个字符了。
/* 不断旋转的光标: | / - / */ const char* lable = "|/-//"; int cnt = 0; while (cnt <= TIMES) { printf("[%-100s] [%d%%] ... %c/r", bar, cnt, lable[cnt % 4]); // 改成/r
运行结果如下:
翻过这座山,我们是------冠军!!!!!!!!!
Git 简单介绍
git 是什么?
git是一种代码管理器,写git程序的和写Linux系统的是同一个人,所以Linux可以直接和gitee或GitHub相关联!
GitHub: Let’s build from here · GitHub
Gitee - 基于 Git 的代码托管和研发协作平台
这里使用gitee举例子:先在远端创建仓库
合法的
(我敲~这个为什么是倒着的啊???)
Linux下的gitee创建仓库
在创建好仓库后,复杂https的链接
使用指令: git clone 链接
即可将远端仓库克隆到本地
接下来的操作和Windows上的三板斧相似:
首先在本地仓库创建一份文件:
注意:是在本地仓库里面创建的。
git三板斧之add
我们在当前目录下直接输入指令:
git add 文件名 或 git add .
前者是添加特定的文件到本地仓库
后者是将当前目录下所有文件提交
输入完这条指令后,文件就已经被添加到本地仓库了
那么怎样在本地仓库查看有哪些文件呢?
使用指令:
git status
可以发现,本地仓库中还有test.c
。没有被提交到远端仓库!
git三板斧之commit
请注意,在commit时一定要输入日志
使用指令:
git commit -m "日志"
日志一定不要乱写!
日志一定不要乱写!
日志一定不要乱写!
你的gitee或GitHub,就会去看日志!
比如这里我可以这样写日志:、
输入此指令后,如果你是第一次输入,系统可能会让你输入邮箱和用户名密码,这时系统会将指令的格式给你显示出来,你只需要将格式中引号内的内容改成你的自己的邮箱或用户有即可!
或者你也可以事先输入好
user代表用户,.name代表配置用户的名称
git config --global user.name "你的用户名"
user代表用户,.email代表配置用户的邮箱
git config --global user.email "你的邮箱"
这样就好了
git三板斧之push
在commit输入完日志后,输入指令:
git push
将本地仓库的文件推送至远端仓库!
输入这条指令后,会显示这样的画面:
注:账号最好是输入下面红框里的:
我们登录gitee就会看到:
最后:
大家要维护好自己的gitee或GitHub
一年都百分之80都是小绿点会很加分的!