赞
踩
目录
话不多说我们先上这15行代码
- #include<stdio.h>
- #include<unistd.h>
- int main(){
- #define NUM 100
- char buffer[NUM+1] = {0};//存储进度条字符
- char arr[5] = {"-/|\\"};//存储基本的变化字幕
- for(int i = 0;i<NUM ;++i){
- buffer[i] = '#';
- printf("[%-100s][%d%%][%c]\r",buffer,i+1,arr[i%4]);
- fflush(stdout);
- usleep(60000);
- }
- printf("\n");
- return 0;
- }
博主的Gitee码云中也存有15行进度条代码(此外还有更多宝藏代码) , 需要的同学可以自取~
本文将会结合生动形象的例子首先对 行刷新测量 以及 屏幕打印的实质 这两大原理进行讲述 , 再进行进度条代码的书写 , 让你学到的不只是进度条代码本身。
我们首先看一个惊奇的现象 , 先休眠 , 再打印到屏幕上 , 难道printf真的执行的比sleep慢吗?
当然不可能!!!
这个就涉及到printf的封装 , 我们的printf实际上是对系统调用接口的封装 , printf并不直接打印到屏幕上 , printf函数打印到的地方不是屏幕 ! 而是打印到一个C的用户缓冲区中 !
更具体的说 , printf打印的内容是不会直接刷新到屏幕上的 , printf作为一个C的接口函数 , 其打印的内容会首先刷新到C语言用户级别的缓冲区 , 然后再刷新到系统级别的缓冲区最后刷新到屏幕上 。 其中最致命的点就在于 C语言用户级别的缓冲区的内容 什么时候 刷新到系统缓冲区进而到屏幕当中。什么时候刷新用户级缓冲区就涉及到缓冲区的刷新策略问题!
何时刷新 :
C语言用户缓冲区的刷新策略是 行刷新策略 , 也就是说 , 之后在用户缓冲区中出现了 \n 行号时 , 才会将现在缓冲区的内容都刷新到 系统缓冲区 进而刷新到屏幕。
或者只有当整个程序退出的时候 , 才会将用户级缓冲区内的内容全部刷新出来。
举个例子 :
事实上 , printf是对系统调用接口打印的封装 , 只有系统调用接口是直接和系统缓冲区打交道 , 而printf接口是对系统接口的封装 , 所以用户级缓冲区&&用户级缓冲区的行刷新策略是printf这种做封装后的函数所特有的东西。
总结 :
其实你只需要记住 1. printf的实质是把print的内容写入到C语言用户缓冲区中。
2. C用户缓冲区的刷新策略是遇到\n换行才会将C用户缓冲区的内容刷新出去到屏幕。
认识了printf的实质以及C用户缓冲区的行刷新策略 , 我们再认识一下fflush接口 , 可以强制把我们的C用户级缓冲区的内容进行直接到屏幕的刷新。(可以不拘泥于有\n才能进行刷新)
屏幕上可以看作分成了一个一个的小格子 , 打印的实质就是在屏幕上覆盖这些小格子 , 然后用户就能看到屏幕上覆盖的字符图案了。
换行\n , 精确的说是定位到下一行的行首。
回车\r , 精确的说是定位到当前的行首。
示例 :
printf("abc\r");
fflush(stdout);
printf("ef");
这三行代码的执行就是先覆盖打印 abc , 再定位从该行的行首开始打印覆盖 。
将abc\r打印出去之后 , 我们再打印ef就会覆盖后面的字符 , 也就是说现在显示的就是ef。
进度条思路的构建 :
进度条实际上就是在屏幕的同一行中 , 在短时间间隔中不间断回到首行并覆盖打印越来越多的字符 , 例如我先打印一个# , 在0.01s后\r回到该行首行 , 再从行首位置向后覆盖打印两个## , 0.01s后再\r回到该行的首行 , 再打印三个###进行该行的覆盖打印 ....... 如此不间断的 进入首行+往后覆盖打印 , 就可以实现进度条的显现。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。