【Linux】9.Linux第一个小程序进度条
文章目录
- Linux第一个小程序-进度条
- 相关知识
- 创建程序
- 1. 程序原理
- 2. 基础程序原理实现
- 井号进度条代码实现
- 箭头进度条代码实现
- 多重进度条代码实现
Linux第一个小程序-进度条
相关知识
特殊符号:
$@
和$^
回车换行:
回车和换行其实是两个东西。
回车:挪到下一行的最前面。
换行:挪到下一行的当前位置,就是从上往下。
缓冲区:
创建程序
1. 程序原理
我们先创建一个文件夹,进去
然后创建3个文件
然后进入processBar.h
,写一下
然后往main.c
里面写一点东西。
然后创建makefile
文件,进去编写代码
processbar:processBar.c main.c
gcc -o $@ $^
.PHONY:clean
clean:
rm -f processbar
然后进入main.c
,修改代码
# include "processBar.h"
#include <unistd.h>
int main()
{
printf("hello world\n");
sleep(2);//这个要用到unistd.h头文件
return 0;
}
现象是先打印hello world
,然后休眠2s
。
然后进入main.c
,修改代码,去掉\n
,那么现象会是什么呢?
是先打印hello world
,然后休眠2s
还是先休眠2s
,然后打印hello world
呢?
# include "processBar.h"
#include <unistd.h>
int main()
{
printf("hello world");//1
sleep(2); //2
return 0;
}
得到的现象是先休眠2s
,然后打印hello world
。
咦,怎么会这样?难道先执行了第二条语句,然后执行第一条语句吗?
当然不是。
C
语言是按顺序执行的,所以执行顺序一定是先执行第一条语句,再执行第二条语句。
那为什么会这样呢?
sleep
期间,printf
语句执行完了,那么它在这两秒内怎么了呢?
因为后面还是打印出来了,说明printf
一定被保存起来了。
保存在了C
语言的缓冲区,这个缓冲区就是指由C
语言维护的一段内存。
如果我要强制刷新呢?
C
语言文件默认打开3个文件:标准输入流,标准输出流(显示器显示),标准错误流
我们继续更改一下main.c
文件,添加一行代码:
# include "processBar.h"
#include <unistd.h>
int main()
{
printf("hello world");//1
fflush(stdout); // 强制刷新标准输出缓冲区
sleep(2); //2
return 0;
}
再次运行的结果就不一样了,现象是先打印hello world
,然后休眠2s
。
关键点解释:
printf("hello world");
- 将字符串输出到标准输出
- 但由于缓冲机制,不一定立即显示在屏幕上
- 内容可能暂存在缓冲区中
fflush(stdout);
- 强制刷新标准输出缓冲区
- 确保"hello world"立即显示在屏幕上
- 不使用fflush时,内容可能要等到缓冲区满或程序结束才显示
sleep(2);
- 让程序暂停执行2秒
- 单位是秒
- 这期间程序什么都不做
如果去掉
fflush(stdout)
:
- "hello world"可能要等到程序结束才显示
- 因为程序很快就结束了,用户可能看不到2秒暂停的效果
2. 基础程序原理实现
好的 ,通过上面的原理,应该都知道了缓冲区的存在了。
比如我们输入一个9,那么光标就跑到9的后面了。
我们在9的前面输入一个8,那么9就被挤到8的后面了,得到了89
我们进入main.c
文件,更改一下代码:
# include "processBar.h"
#include <unistd.h>
int main()
{
//倒计时
int cnt = 9;
while(cnt){
printf("%d",cnt);
fflush(stdout);
cnt--;
sleep(2);
}
//printf("hello world");//1
//fflush(stdout);
//sleep(2); //2
return 0;
}
得到:
但是这个不是让光标回到最开始写的,怎么修改呢?
我们加个\r
就可以了
# include "processBar.h"
#include <unistd.h>
int main()
{
//倒计时
int cnt = 9;
while(cnt){
printf("%d\r",cnt);
fflush(stdout);
cnt--;
sleep(2);
}
printf("\n");
//printf("hello world");//1
//fflush(stdout);
//sleep(2); //2
return 0;
}
打印:
实现了一个简单的倒计时。
不过表面上看起来我们实现的很完美,可是如果倒计时变成两位数的话:
# include "processBar.h"
#include <unistd.h>
int main()
{
//倒计时
int cnt = 10;
while(cnt>=0){
printf("%d\r",cnt);
fflush(stdout);
cnt--;
sleep(2);
}
printf("\n");
//printf("hello world");//1
//fflush(stdout);
//sleep(2); //2
return 0;
}
程序打印为:
10 --> 90 -->80。。。
因为打印的是字符。
这里我们只需要加一个-2就可以了,%-2d
一次打印两个字符,而且是左对齐。
# include "processBar.h"
#include <unistd.h>
int main()
{
//倒计时
int cnt = 10;
while(cnt>=0){
printf("%-2d\r",cnt);
fflush(stdout);
cnt--;
sleep(2);
}
printf("\n");
//printf("hello world");//1
//fflush(stdout);
//sleep(2); //2
return 0;
}
井号进度条代码实现
processBar.c
#include "processBar.h"
#include <string.h>
#include <unistd.h>
const char *lable="|/-\\";
void processbar()
{
char bar[NUM];
memset(bar,'\0',sizeof(bar));
int len=strlen(lable);
int cnt=0;
while(cnt<=100)
{
printf("[%-100s][%d%%][%c]\r",bar,cnt,lable[cnt%len]);
fflush(stdout);
bar[cnt++]=STYLE;
usleep(100000);
}
printf("\n");
}
processBar.h
#pragma once
#include <stdio.h>
#define NUM 102
#define STYLE '#'
extern void processbar();
main.c
# include "processBar.h"
#include <unistd.h>
int main()
{
processbar();
return 0;
}
实现效果:
箭头进度条代码实现
processBar.c
#include "processBar.h"
#include <string.h>
#include <unistd.h>
const char *lable="|/-\\";
void processbar()
{
char bar[NUM];
memset(bar,'\0',sizeof(bar));
int len=strlen(lable);
int cnt=0;
while(cnt<=100)
{
printf("[%-100s][%d%%][%c]\r",bar,cnt,lable[cnt%len]);
fflush(stdout);
bar[cnt++]=STYLE;
if(cnt <=100) bar[cnt]='>';
usleep(100000);
}
printf("\n");
}
processBar.h
#pragma once
#include <stdio.h>
#define NUM 102
#define STYLE '-'
extern void processbar();
main.c
# include "processBar.h"
#include <unistd.h>
int main()
{
processbar();
return 0;
}
实现效果:
多重进度条代码实现
processBar.c
#include "processBar.h"
#include <string.h>
#include <unistd.h>
const char *lable="|/-\\";
char bar[NUM];
void processbar(int rate)
{
if(rate<0||rate>100) return;
int len=strlen(lable);
printf("[%-100s][%d%%][%c]\r",bar,rate,lable[rate%len]);
fflush(stdout);
bar[rate++]=BODY;
if(rate <100) bar[rate]=RIGHT;
}
void initbar()
{
memset(bar,'\0',sizeof(bar));
}
processBar.h
#pragma once
#include <stdio.h>
#define NUM 102
#define TOP 100
#define BODY '='
#define RIGHT '>'
extern void processbar(int rate);
extern void initbar();
main.c
# include "processBar.h"
#include <unistd.h>
typedef void (*callback_t)(int);
void downLoad(callback_t cd)
{
int total = 1000; //1000MB
int curr = 0; //0MB
while(curr <= total){
usleep(50000);
int rate=curr*100/total;
cd(rate);
curr+=10;
}
printf("\n");
}
int main()
{
printf("download 1: \n");
downLoad(processbar);
initbar();
printf("download 2: \n");
downLoad(processbar);
initbar();
printf("download 3: \n");
downLoad(processbar);
initbar();
printf("download 4: \n");
downLoad(processbar);
initbar();
return 0;
}
实现效果: