玩转Linux进度条

准备工作:

一.关于缓冲区

首先,咱们先来一段有意思的代码:

复制代码
#include<stdio.h>
#include<unistd.h>
int main()
{
      printf("you can see me");
      sleep(5);

}

你可以在你的本地运行一下,这里我告诉大家运行结果:这一段字符串等到程序运行结束后才被显示出来。有些同学感觉非常震惊,但这就是运行结果。

我们都知道,这段代码是顺序运行结构,就是从前往后依次执行,毫无疑问,这段字符串肯定被优先执行,那么,为什么没有被显示出来?这5秒内,字符串在什么位置?

字符串一直在缓冲取内,等到运行结束时,才被刷新出来。那,怎么才能让字符串在sleep前出现呢?

这里,我说明两种方式:

方式一:

复制代码
#include<stdio.h>
#include<unistd.h>
int main()
{
      printf("you can see me\n");
      sleep(5);

}

在printf中加入换行符,因为\n默认的是行刷新,

cpp 复制代码
#include<stdio.h>
#include<unistd.h>
int main()
{
      printf("you can see me\n");
      printf("you can see ");
      sleep(5);

}

我们来运行一下,会发现:第一字符串打印出来了,第二个字符串等到程序结束时,才显示出来!

方式二:

cpp 复制代码
#include<stdio.h>
#include<unistd.h>
int main()
{
      printf("you can see me\n");
      fflush(stdout)
      sleep(5);

}

fflush(stdout)表示手动刷新缓冲区的操作。

二.\r,\n

\r是回车,\n是换行,所以\r\n 是回车换行,但是在语言层面,\n就代表着回车+换行。

我们举个栗子:

cpp 复制代码
#include<stdio.h>
int main()
{
	printf("aaaaa\r");
	printf("11");
	return 0;
}

运行结果是:

果真像我们分析的那样,程序运行完第一行,"aaaaa"被打印出来,然后光标回到行首,开始打印"11",这个位置原来的数据被后来的数据所覆盖,所以打出来,就是这个样子。

三.关于显示屏

其实,不知道大家有没有好奇过:我们的数字和字母都是怎么出现在显示屏的呢?原理很简单!!

在显示屏看来,不过是字符还是数组还是汉字,都是由字符构成,比如在显示屏上打印出1234,显示屏就把1234看作4个字符,然后点亮这4个字符的光点,所以,我们就看见了1234。

四.制作一个一分钟倒计时

cpp 复制代码
#include<stdio.h>
#include<unistd.h>
int main()
{
	int num = 60;
	while (num)
	{
		printf("%d\r", num);
		fflush(stdout);
		num--;
	}
}

二.制作一个进度条

效果演示:

写在前面,这个进度条,我们准备分文件写,分别为main.cc,process.cc,process.h,下面,将一一介绍各个文件的作用:

进度条代码:

makefile:

cpp 复制代码
myproc:process.cc main.cc 
	gcc -o myproc process.cc main.cc //-o后边的文件默认为生成的文件,其他的都是依赖文件
.PHONY:clean
clean:
	rm -f myproc

main.cc:

cpp 复制代码
#include "process.h"

int main()
{
    myprocess();
    
}

代码so easy!!

process.h:

cpp 复制代码
#include<stdio.h>
#include<string.h>
#include<unistd.h>


#define Num 101
#define STYLE '#'


const char lable[]="|/-\\";
extern void myprocess();

process.cc:

cpp 复制代码
#include "process.h"


void myprocess()
{
   int cnt=0;
   char buf[Num];
   memset(buf,'\0',sizeof buf);//利用字符串初始化函数,初始化字符串为0;
   while(cnt<Num)
   {

        if(cnt<Num-1)buf[cnt]=TAIL;
        printf("[%-100s][%-3d%%][%c]\r",buf,cnt,lable[cnt%4]);//[%-100s]:先留出100个字符的长度,保证从前往后显示;%%:表示百分号
        buf[cnt++]=STYLE;
       
        fflush(stdout);
        usleep(50000);//usleep:和sleep效果相同,但usleep以微妙为单位,但sleep以秒为单位
   }
 
   printf("\n");
}

3、实现过程分析

进度条样式 :

主体样式为两个中括号包裹,中间 => 推进的方式呈现,比如:======\>

主体右侧中括号位置保持不变,中间元素不断推进,比如:=\>

因此我们把中间主体 = 宏定义为 STYLE,把尾侧 > 宏定义为 TAIL

进度条百分比:

显示当前加载进度,用 rate% 显示,rate 随着进度条的不断推进而变化,而打印 %(转义字符)则需要两个 %%

进度条旋转字符:

显示加载样式,可以利用一个旋转的字符,例如 \[\] 的样式,顺时针不断旋转,依次为 "| / - \",注意 \ 也是转义字符,因此需要两个 \ \,对此我们定义一个lable指针指向常量字符串const char *lable=" | / - \ "

相关推荐
6Hzlia5 分钟前
【Classic 150 刷题计划】 LeetCode 205. 同构字符串 | C++ 双向绑定与哈希表映射
c++·算法·leetcode
酣大智1 小时前
网络协议计时器 & 发包间隔汇总
运维·网络·tcp/ip
有点。7 小时前
C++03阶段练习(练习题)
数据结构·算法·图论
云运维笔记7 小时前
IP地址从入门到精通:网络通信的核心基石
运维·网络·计算机网络
bosins8 小时前
WSL2 启动即崩溃?调整超时参数解决 Docker 阻塞问题
linux·docker·wsl
周末也要写八哥8 小时前
经典算法实例:游戏中弱角色的数量(二)
算法
是Yu欸8 小时前
鸿蒙PC移植:2048 从网页小游戏到 AI 桌面应用
大数据·人工智能·算法·数据挖掘·openharmony·codex
鹿角片ljp8 小时前
KV Cache 解析
java·算法
web守墓人8 小时前
【goed/ui】自定义组件设计思想篇
linux·windows·ui·golang
码农学院9 小时前
企业官网改版后 AI 引用归零的复盘:301 重定向断层让爬虫索引掉线,修复方案与恢复数据
运维·geo优化·ai优化aio