预备知识
缓冲区
先看下面两段代码
c
int main()
{
printf("hello world\n");
sleep(2);
return 0;
}
c
int main()
{
printf("hello world");
sleep(2);
return 0;
}
第一段代码会直接显示hello world
,然后等待两秒,程序结束。第二段代码,则会先等待两秒,在显示hello world
。由此可以得出printf
函数已经跑完,输出的字符串一定是被保存了起来,在退出的时候才能刷新出来。输出的字符串被保存的地方就是对应的缓冲区
回车与换行
换行:指的是光标从一行换到另一行的对应位置
回车:指的是光标回到这一行的最前面
回车对应的转义字符为\r
下面先来练习写一个倒计时的代码
c
#include <stdio.h>
#include <unistd.h>
int main()
{
int cnt=10;
while(cnt)
{
printf("%-2d\r", cnt--);
fflush(stdout);
sleep(1);
}
return 0;
}
fflush
函数会直接把缓冲区里的内容刷新到屏幕上
所用到的函数
c
#include <unistd.h>
unsigned int sleep(unsigned int seconds);//当程序在运行时,执行到sleep时休眠上seconds秒
c
#include <stdio.h>
int fflush(FILE*stream);//强制刷新一个流,(可以将缓冲区里的内容强制刷新到屏幕上)
c
#include <unistd.h>
int usleep(useconds_t usec);//休眠的时间单位是微秒
项目源码
processbar.h
c
#pragma once
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define NUM 103
#define Body '='
#define Head '>'
typedef void (*callback_t)(double);
//version 1
void process();
void process_flush(double rate);
processbar.c
c
#include "processbar.h"
const char* lable="|/-\\";
void process()
{
char buffer[NUM];
memset(buffer, '\0',sizeof(buffer));
int cnt = 0;
int n=strlen(lable);
buffer[0]=Head;
while(cnt <= 100)
{
printf("[%-100s][%-3d%%][%c]\r", buffer, cnt, lable[cnt%n]);
fflush(stdout);
buffer[cnt++] = Body;
if(cnt<100)
buffer[cnt] = Head;
usleep(10000);
}
printf("\n");
}
char buffer[NUM] = { 0 };
void process_flush(double rate)
{
static int cnt = 0;
int n = strlen(lable);
if(rate <= 1.0)
buffer[0]=Head;
printf("[%-100s][%-5.1lf%%][%c]\r", buffer, rate, lable[cnt%n]);
fflush(stdout);
buffer[(int)rate] = Body;
if(rate<99)
buffer[(int)rate+1] = Head;
if(rate >= 100.0)
printf("\n");
cnt++;
cnt%=n;
}
main.c
c
#include "processbar.h"
#include <time.h>
#include <stdlib.h>
#define FILESIZE 1024*1024*1024
// 模拟下载任务
void download(callback_t cb) // 回调函数的形式
{
srand(time(NULL));
int total = FILESIZE;
while(total)
{
usleep(5000);
int one = rand()%(1024*1024*5);
total -= one;
if(total < 0)
total = 0;
// 当前的进度
int download = FILESIZE - total;
double rate = (download*1.0/(FILESIZE))*100.0;
cb(rate);
}
}
int main()
{
//process();
download(process_flush);
return 0;
}
makefile
makefile
processbar:main.o processbar.o
gcc -o $@ $^
main.o:main.c
gcc -c main.c
processbar.o:processbar.c
gcc -c processbar.c
.PHONY:clean
clean:
rm -rf main.o processbar.o processbar