Linux第一个小程序——进度条
- 1. 前言
- 2. 缓冲区概念
- 3. \r && \n
- 4. 进度条实现
- 4.1 初级进度条
- 4.2 升级进度条
1. 前言
在我们写这个小程序之前,我们要用到我们学的三个知识点
- gcc的使用
- vim的使用
- make/makefile的使用
除此之外还需要一些其他的知识点,但是这里重点是上面的三个知识点。所以如果由对这三个知识点不了的一定要先熟悉这三个知识点。
2. 缓冲区概念
- 这里学一个函数和一个头文件。
首先执行指令man 3 sleep查看第三手册手册。
函数sleep,头文件<unistd.h>
作用:休眠指定的秒数。
函数usleep,头文件<unistd.h>
作用:休眠指定的微秒。
-
现在我们来写一段代码来证明这个缓冲区的存在。
此时我们直接执行,是会直接显示打印出来的。
现在我们稍作改动一下,把打印hello Linux/n中的换行\n去除再次执行。
-
我们先来分析一下。首先我们C语言有一种结构叫做顺序结构,也就是代码是从上到下依次执行的,不存在跳跃的情况,也不存先执行后面的再到过来执行前面的。也就是说上面的无论是哪一种情况都是printf先被执行然后才是sleep被执行的。那么为甚第二种情况我们在执行可执行程序的时候没有立马打印出结果来呢?而是过来3秒后也就是sleep(3)后才打印出结果来呢?理由只有一个,那就是我们在执行到printf的时候,是将printf里面的值保存起来后再去执行的sleep,而保存的地方就是我们的缓冲区。等到程序结束了,再从缓冲区中取出数据打印显示在显示屏上。而至于为什么第一种直接打印出来了呢?
是因为/n有刷新缓冲区的作用
,当缓冲区拿到数据并保存起来的时候,可以通过刷新缓冲区拿到数据。
3. \r && \n
大多数的人都认为回车跟换行是一回事。但是换行和回车其实是两回事。所谓换行,是执行到当前行的位置后,执行到当前位置的映射的垂直下的那个位置。而回车是执行到当前行位置后,回到开头。
之所以我们一直认为是同一回事,是因为我们通常在键盘上按回车,其实是同时执行了回车和换行,所以会另起一样并从头开始。
4. 进度条实现
4.1 初级进度条
#include <stdio.h>
#include <unistd.h>
#include <string.h> #define NUM 103
int main()
{ char arr[NUM]; arr[0] = '>'; int count = 0; memset(arr,'\0',sizeof(arr)); while (count <= 100) { printf("%-100s\r",arr); fflush(stdout); arr[count++] = '='; if (count < 100) arr[count] = '>'; usleep(100000); } printf("\n"); return 0;
}
此时一个简单的进度条就完成了。
4.2 升级进度条
但是,这个只是我们模仿出来的进度条。
但是实际上的进度条是附加在其他上面的,比如下载大小上的。
- makefile
processbar:main.c processbar.cgcc -o $@ $^.PHONY:clearclear:rm main.o processbar.o processbar
- processbar.c
char buffer[NUM] = {0};
void process_flush(double rate)
{int n = strlen(laber);static int count = 0; if (rate <= 1.0) buffer[0] = HEAD;fflush(stdout);printf("[%-100s][%.1lf%%][%c]\r",buffer,rate,laber[count % n]);buffer[(int)rate] = BODY;if ((int)rate + 1 < 100) buffer[(int)rate + 1] = HEAD;if(rate >= 100.0) printf("\n"); count ++;count %= n;
}
- processbar.h
#pragma once
#include <stdio.h>
#include <string.h>
#include <unistd.h>#define NUM 103
#define HEAD '>'
#define BODY '='
typedef void(*call_func)(double);//重命名process_flush函数指针类型void process();
void process_flush(double rate);
- main.c
#include "processbar.h"
#include <time.h>
#include <stdlib.h>
#define FILESIZE 1024*1024*1024void downlode(call_func rq)
{ srand((unsigned int)time(NULL)); int total = FILESIZE; while(total) { usleep(5000); //下载速度 int dw_speed = rand()%1024*1024*5; total -= dw_speed; if (total <= 0) total = 0; int download = FILESIZE - total; double rate = (download * 1.0 / (FILESIZE)) * 100; rq(rate); }
}
int main()
{ downlode(process_flush); return 0;
}
- 执行结果