缓冲区
在写进度条程序之前我们需要介绍一下缓冲区,缓冲区有两种,输入和输出缓冲区,这里主要介绍输出缓冲区。在我们用C语言写代码时,输出一些信息,实际上是先输出到输出缓冲区里,然后才输出到我们的显示器上。
原因是:
如果输出一个字符就打印到显示器上,那么就会有大量的IO交流在显示器上,外设的速度比较慢,这会降低系统效率,所以就有缓冲区减少IO次数,等我们手动或者达到一定条件(进程结束)时缓冲区刷新就会打印信息到显示器上
看下面两段代码:
1 #include<stdio.h>
2 #include<unistd.h>
3
4 int main()
5 {
6 printf("123");
7 sleep(2);
8 return 0;
9 }
这段代码先等待2秒然后才输出123,因为
printf
先输出123到缓冲区中,等2秒后程序结束刷新缓冲区就把信息打印到显示器上
1 #include<stdio.h>
2 #include<unistd.h>
3
4 int main()
5 {
6 printf("123\n");
7 sleep(2);
8 return 0;
9 }
这段代码是先打印123,然后等2秒程序结束,
\n
能手动刷新缓冲区,所以是先打印123然后等2秒程序结束
\n&&\r
\r
是回车,就是光标回到当前行第一位,\n
是换行,就是光标移动到当前位置下一行。我们键盘上的Enter
是换行加回车一起进行的。
进度条的实现
实现进度条之前我们先写好我们的makefile
文件:
myexe:test.c process.c
@gcc -o $@ $^
.PHONY:clean
clean:
@rm -f myexe
version1
v1版本就是一个普通进度条,只有样式
process.h
1 #pragma once 2 #include<stdio.h> 3 #include<unistd.h> 4 #include<string.h> 5 6 void process(); //声明函数
process.c
1 #include"process.h" 2 3 #define SIZE 100 4 #define SLEEPTIME 1000*50 5 #define STYLE '#' 6 7 char str[SIZE+1]={0}; 8 char wait[]={"|/-"}; 9 10 void process() 11 { 12 int rate = 0, wsize = strlen(wait); 13 while(rate <= SIZE) 14 { 15 printf("[%-100s][%d%%][%c]\r",str,rate,wait[rate%wsize]); //输出格式 16 fflush(stdout); //刷新缓冲区 17 usleep(SLEEPTIME); //等待 18 str[rate++] = STYLE; //增加'#' 19 } 20 printf("\n"); 21 }
test.c
1 #include"process.h" 2 3 int main() 4 { 5 process(); //调用函数 6 return 0; 7 }
version2
v2版本的进度条根据实际情况进行变化的,符合实际
process.h
#pragma once #include<stdio.h> #include<unistd.h> #include<string.h> typedef void (*callback_t)(int); //重定义函数指针 void process_v2(int rate);
process.c
#include"process.h" #define SIZE 100 #define STYLE '#' char str[SIZE+1]={0}; char wait[]={"|/-\\"}; int cnt = 0; void process_v2(int rate) { cnt++; //当进度卡住时,指示标还会一直转动,表示正在下载 int size = strlen(str); while(size < rate) //判断当前进度条的符号数量是否符合传进来的进度 str[size++] = STYLE; if(rate >= 0 && rate <= SIZE) //判断rate合法性 { int wsize = strlen(wait); printf("[%-100s][%d%%][%c]\r",str,rate,wait[cnt%wsize]); fflush(stdout); } }
test.c
#include"process.h" #define TARGET 1024*1024 #define DOWNLOAD 5000 void download(callback_t cb) { int cur = 0; while(1) { cur += DOWNLOAD; //下载ing int rate = (cur*100)/(TARGET); //计算当前进度 if(rate > 100) //判断rate是否合法 rate = 100; cb(rate); //回调函数 if(rate >= 100) //如果进度已经打到100就退出 break; usleep(10000); //模拟下载等待时间 } printf("\n"); } int main() { download(process_v2); return 0; }
version3
v3版本是外观美化
可以对格式进行更改,加点文字描述,以及更改颜色和底色,详情百度,这里就不再赘述