前言
进度条实质
我们所实现的进度条小程序的实质时在一定的空间内不断刷新元素的过程,并不是真正意义的增加
长度,因此我们需要先了解一些知识。
\r 与 \n
在真正写程序之前,我们需要知道‘\n’本身是代表换行(即向下移动一行,并不改变当前左右)
‘\r’代表回车(移动到当前行的最左侧)
而在Linux和C语言中‘\n’表示换行回车
缓冲区
缓冲区本身是一块内存空间,分为
- 无缓冲(无缓冲区,立即执行)
- 行缓冲(遇到’\n’把’\n’之前的内容全部执行)
- 全缓冲(缓冲区满的时候再执行)
- 程序退出,缓冲区数据自动刷新
而我们在linux中用c写进度条的代码时,实际上是行缓冲
对于这样一个代码,linux中会先sleep后打印,因为printf中的内容被临时存放在缓冲区中
但进度条程序不能使用’\n’的,此时我们使用fflush进行缓冲区的刷新
而C语言默认为我们打开了stdin,stdout,stderr,我们实际使用的是stdout(对应显示器)
由此上图代码块就是一个简易的倒计时,(因为是行刷新,如果没有fflush屏幕什么都不会打印)
代码
Makefile
makefile/make的使用也是基础重要的知识,不清楚的可以看这里
procbar:ProBar.c Main.c
gcc ProBar.c Main.c -o procbar
.PHONY:clean
clean:
rm -f procbar
ProBar.h
进度条程序所需要的头文件
#pragma once
#include <stdio.h>
#include <unistd.h>
#define NUM 101
void progress_bar();
ProBar.c
进度条源文件即函数实现部分,下面进行分析解释
#include "ProBar.h"
void progress_bar()
{
char bar[NUM];
memset(bar, '\0', sizeof(bar));
int i = 0;
const char* symbol = "| / -- \\";
while (i <= 100)
{
printf("[%-100s][%-3d%%][%c]\r", bar, i, symbol[i % 8]);
fflush(stdout);
bar[i++] = '=';
usleep(30000);
}
printf("\n");
}
我们从上往下慢慢分析
首先需要初始化一个进度条本体的逐渐增多的框框
char bar[NUM];
memset(bar, '\0', sizeof(bar));
这里我们使用memset把数组元素初始化为’\0’(直接={0}也可以)
接下来是循环内部(进度条本体打印)
while (i <= 100)
{
printf("[%-100s][%-3d%%][%c]\r", bar, i, symbol[i % 8]);
fflush(stdout);
bar[i++] = '=';
usleep(30000);
}
- 进度条框中[%-100s]中%100s是预留空间,而在C语言中预留空间后会从右向左输入信息,故加符号使其从左开始输出。
- [%-3d%%]是记录加载位置数据的,后面两个%%输出为一个%。
- symbol[i%8]避免超出字符串
- 因为Linux中sleep的单位是秒,这里使用usleep(微秒),可以更快的输出
const char* symbol = "| / -- \\";
当程序执行卡死可以有标志,此字符串通过构建一个持续转圈的小指标作为判断标志