进度条—实例示范
在学习了基本的Linux指令,Linux上vim编译器等等之后,我们就来学习写代码喽~
今天就给大家详细讲解一下进度条的编写,需要的效果如下图:
进度条—必备知识
回车和换行
在我们学习编程语言中,经常使用的 [ \n ] ,是什么意思呢?
- C 语言中有很多字符,而字符大体分为两类:可显字符、控制字符。
- 控制字符不可显示,例如 \r 和 \n 就是控制字符。
而在我们平时打字时,一行写满了需要换行,其实只根据字面思想来看,换行就是单纯地换行,也就是使光标跳到下一行就是换行。但是这也仅仅只是换行,如下图光标是在行尾的下面,也就是第一行的行尾,所以这是符合我们习惯的。
我们通常的习惯是,在第二段的最左端开始新一行的内容,而要是光标从上一行的行尾,跳到下一行的最左端就应该是两个动作的:换行和回车。
回车就是回到本行的文本行的开头。
所以在编程语言中, [ \n ] 其实两个动作:
- [ \n ] :换行 + 回车;
那么什么是回车呢?
- [ \r ] :换行 。
缓冲区
必备知识点
sleep
- sleep:Linux 下的休眠函数,单位是秒。头文件为 #include <unistd.h>。
sleep的效果样式,如下图,系统就会休眠3秒。
如下例子,当我们将 [ \n ] 删掉,运行程序我们发现下面会出现:
光标一直闪烁,但是一直都不打印,这似乎是在等待sleep3秒结束之后,因为没有 [ \n ] ,所以也一直等到程序结束时,与shell命令行提示一起打印出来,shell提示符紧跟字符串后面显示。
这反而像是sleep函数先起作用,然后printf函数再从光标处开始打印。
#include <stdio.h>
#include <unistd.h>
int main()
{
//printf("hello world,hello world...\n");
printf("hello world,hello world...");
sleep(3);
return 0;
}
加上 [ \n ] 与 不加 [ \n ] 的区别似乎就是:
- 加上 [ \n ]:printf执行结束,字符串直接显示出来,然后sleep;
- 不加 [ \n ]:字符串没有打印出来,先sleep之后,字符串才打印出来。
那么在第二种代码情况下,printf与sleep函数哪个先运行呢?
- 当然是printf先显示出来;
- 因为这串字符串并没有换行符,所以打印的字符串必须与命令行的下一行为同一行;
- C语言执行代码时,永远都是从上往下执行的;
- 在sleep期间,printf的字符串已经打印出来了,只是这串字符串没有显示出来罢了;
- 在sleep之后,消息才显示出来。
那么既然printf的字符串已经打印出来了,只是没有显示出来,在sleep期间,字符串是在哪里的呢?
- 缓冲区
缓冲区理解
缓冲区,可以理解为一块内存空间。
当进行printf打印字符串的时候,字符串被拷贝到了缓冲区,sleep之后,字符串被从缓冲区刷新到显示器,这样就在屏幕上打印出来了字符串了。
一般在程序结束时候或者等到缓冲区满的时候,自动冲刷缓冲区。
缓冲区默认是行刷新的,遇到 [ \n ] 就刷新。
刷缓冲区方式
那么如果不想等到程序结束的时候,直接冲刷缓冲区,如何做呢?
- [ \n ];
- 缓冲区已满;
- 强制刷新。
在打印字符串的后面加上一行强制冲刷缓冲区的代码:
- fflush(stdout) :刷新缓冲区。
fflush(stdout);
#include <stdio.h>
#include <unistd.h>
int main()
{
//printf("hello world,hello world...\n");
printf("hello world,hello world...");
fflush(stdout);//强制冲刷缓冲区
sleep(3);
return 0;
}
实现倒计时
光标和显示器匹配,光标在哪里,显示器打印的时候就从哪里开始打印 。
#include <stdio.h>
#include <unistd.h>
int main()
{
int cnt=10;
while(cnt>=0)
{
printf("倒计时:%2d\r",cnt);
sleep(1);
fflush(stdout);
cnt--;
}
printf("\n");
return 0;
}
进度条代码
“ProgressBar.h”头文件
#include "ProgressBar.h"
#include <unistd.h>
//download
double bandwidth=1024*1024*1.0;
void download(double filesize,callback_t cd)
{
double current=0.0;
double bandwidth=1024*1024*1.0;
printf("download done,current:%lf\n",current);
while(current<=filesize)
{
cd(filesize,current);
//从网络中获取数据
current+=bandwidth;
usleep(10000);
}
printf("\ndownload done,filesize:%lf\n",filesize);
}
int main()
{
//ForTest();
//ProgBar(100.0,10.34);
//ProgBar(100.0,20.34);
//ProgBar(100.0,99.98);
//ProgBar(100.0,56.74);
//ProgBar(100.0,69.98);
download(100*1024*1024,ProgBar);
download(50*1024*1024,ProgBar);
download(800*1024*1024,ProgBar);
download(890*1024*1024,ProgBar);
download(67*1024*1024,ProgBar);
download(10*1024*1024,ProgBar);
return 0;
}
“ProgressBar.c”函数文件
#include "ProgressBar.h"
#include <string.h>
#include <unistd.h>
//version 1
//#define Length 101
//#define Style '#'
//const char* lable="|/-\\";
//void ProgBar()
//{
// char bar[Length];
// memset(bar,'\0',sizeof(bar));
// int len =strlen(lable);
// int cnt=0;
// while(cnt<=100)
// {
// printf("[%-100s][%3d%%][%c]\r",bar,cnt,lable[cnt%len]);
// fflush(stdout);
// bar[cnt++]=Style;
// usleep(100000);
// }
// printf("\n");
//}
#define Length 101
#define Style '#'
const char* lable="|/-\\";
//version 2
void ProgBar(double total,double current)
{
char bar[Length];
memset(bar,'\0',sizeof(bar));
int len =strlen(lable);
int cnt=0;
double rate=((current*100.0)/total);
int loop_count=(int)rate;
while(cnt<=loop_count)
{
bar[cnt++]=Style;
}
printf("[%-100s][%.1lf%%][%c]\r",bar,rate,lable[cnt%len]);
fflush(stdout);
}
“Test.c”测试文件
#include "ProgressBar.h"
#include <unistd.h>
//download
double bandwidth=1024*1024*1.0;
void download(double filesize,callback_t cd)
{
double current=0.0;
double bandwidth=1024*1024*1.0;
printf("download done,current:%lf\n",current);
while(current<=filesize)
{
cd(filesize,current);
//从网络中获取数据
current+=bandwidth;
usleep(10000);
}
printf("\ndownload done,filesize:%lf\n",filesize);
}
int main()
{
//ForTest();
//ProgBar(100.0,10.34);
//ProgBar(100.0,20.34);
//ProgBar(100.0,99.98);
//ProgBar(100.0,56.74);
//ProgBar(100.0,69.98);
download(100*1024*1024,ProgBar);
download(50*1024*1024,ProgBar);
download(800*1024*1024,ProgBar);
download(890*1024*1024,ProgBar);
download(67*1024*1024,ProgBar);
download(10*1024*1024,ProgBar);
return 0;
}