Linux小程序之进度条

> 作者简介:დ旧言~,目前大二,现在学习Java,c,c++,Python等

> 座右铭:松树千年终是朽,槿花一日自为荣。

> 目标:自己能实现进度条

> 毒鸡汤:

> 望小伙伴们点赞👍收藏✨加关注哟💕💕

🌟前言

咱们学习这么久的指令,一句话来概括,都忘光咯,学个锤锤😟😟😟,感觉白学了,博主也是感同身受,毕竟没有相应的练习,很容易遗忘,咱们只要记住主要的指令就可以了,忘了或者不熟咱就查查文档。今天捏我们用我们所学的知识编写一个进度条,看看下面:

QQ录屏20231129162350

⭐前景知识一:\r和\n的理解

C语言会提供一些特殊的字符,比如说我们常用的\n,这个字符大家都不陌生,不就是换行嘛,这个我懂,但是还有一个字符\r,这个字符的作用是回车的意思。在这块就有人说不都是一个意思嘛🤔,敲敲这些老铁们的头🙈,当然不可能是一个意思。

🌙理解字符含意

\r(回车):

  • 就是在第二行让光标跳到最开始的位置,这个操作就是回车。

\n(换行):

  • 让光标从第一行跳到第二行,但是光标只是垂直向下跳,并没有在第二行的开始。这个操作就是换行。

直接说字符的意思就有一点抽象,咱们来个代码看看👻👻👻

🌙代码理解字符

\n(换行):代码

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

int main()
{
   printf("hello world\n");

   return 0;

}

\r(回车):代码

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

int main()
{
   printf("hello world\r");

   return 0;

}

基于上面的原因我这不讲解,在后面的缓冲区里面我们详细讲解。

⭐前景知识二:认识缓冲区

这里我们要知道什么是缓冲区,咱可以看看官方用语:缓冲区处理 - Windows drivers | Microsoft Learn

简单来讲就是:

  • 在内存中预留了一块空间,用来缓冲输入或输出的数据,这个保留的空间被称为缓冲区。

🌙回顾回车和换行

咱们再看看这两张图片:

我们知道用 \n 的话就可以打印出来,而 \r,不能打印出来。

  • 由于显示器模式是行刷新缓冲区是按行缓冲的,没有\n,就不能立即刷新。
  • 由于\r 回到行首后,会进行覆盖写,shell 提示符会覆盖掉之前写的 "hello world"。

🌙sleep和ffush理解

使用这个函数是在<unistd.h>库中,使用它们需要包含头文件 #include <unistd.h>,这里和缓冲区有什么关系🧐,因为在进度条中需要用到这两函数。

咱们先看这些个函数的作用

  • sleep:休眠函数,单位是秒。
  • usleep:休眠函数,单位是ms(10﹣6 )
  • fflush:刷新缓冲区

咱们来个简单的代码看看这些函数作用:

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

int main()
{
   printf("hello world\r"); 
   //刷新缓冲区
   fflush(stdout);
   printf("\n");
   //休眠三秒
   sleep(3);
   return 0;

}

⭐前景知识三:简单倒计时

实现进度条咱们得先实现一下简单的倒计时,为了给进度条铺垫,简单来讲就是当炮灰。

效果演绎:

全部代码:

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

int main()
{
   int cnt = 10;
   while(cnt >= 0)
   {
       printf("%-2d\r",cnt);
       fflush(stdout);
       sleep(1);
       cnt--;
   }
   printf("\n");
   return 0;
}

过程分析:

  • 定义倒计时变量 cnt,让其逐渐递降。
  • 核心就是用 \r 回到缓冲区行首进行覆盖写,然后fflush不断刷新出出来。
  • 格式调整,打印 cnt==10 时,在缓冲区打印的其实是字符1和字符0,如果我们不用 2d% 来调整格式,而用 d% 的话,那么覆盖写只会覆盖第一位字符 1 11 的位置,而第二位的字符 0 00, 还留在缓冲区原来的位置,于是倒计时便会变为下面这样
      10->90->80->70->60->50->40->30->20->10->00 ,-2d% 加个负号保证其向左对齐
  • 倒计时完加个 \n符,shell 提示符就不会出现在倒计时后面。

⭐进度条过程分析

原理:其原理就是不断地覆盖,然后将其像早以前的动画片一样,变成一个动画。

  • 第一个中括号就是表示进度条。
  • 第二个中括号表示进度。
  • 第三个表示旋转样式。

QQ录屏20231129162350

game.h

cpp 复制代码
#include<stdio.h>
#include<time.h>
#include<unistd.h>
 
void game(double rate);
void download();

game.c

cpp 复制代码
#include"game.h"
#define MAX 1024*1024*1024
 
char* buff = "|/-\\";
int i = 0;
char arr[102] = { 0 };
void game(double rate)
{
	if (rate <= 1.0)
	{
		arr[0] = '=';
	}
	printf("[%-100s][%.1lf%%][%c]\r", arr, rate, buff[i % 4]);
	fflush(stdout);
	arr[(int)rate] = '=';
	if (rate< 99.0)
	{
		arr[(int)rate+1] = '>';
	}
	i++;
}
 
void download()
{
	srand(time(NULL)^1023);
	int max = MAX;
	int cnt = 0;
	double rate = 0;
	while (rate<100.0)
	{
		cnt+= rand() % (1024*1024);
		rate = ((cnt*1.0)/max)* 100;
		if (rate > 100)
		{
			rate = 100;
		}
		game(rate);
		usleep(50000);
	}
}

test.c

cpp 复制代码
​
#include"game.h"
 
int main()
{
	download();
	return 0;
}

​

makefile

cpp 复制代码
all:test.o game.o
	gcc -o $@ $^

test.o:test.c
	gcc -c -o $@ $^

game.o:game.c
	gcc -c -o $@ $^

.PHONY:clean
clean:
	rm -rf *.o all

​

🌟结束语

今天内容就到这里啦,时间过得很快,大家沉下心来好好学习,会有一定的收获的,大家多多坚持,嘻嘻,成功路上注定孤独,因为坚持的人不多。那请大家举起自己的小说手给博主一键三连,有你们的支持是我最大的动力💞💞💞,回见。

相关推荐
XH华5 小时前
Linux系统第二章:常见的Linux指令(上)
linux·运维·服务器
FoldWinCard15 小时前
D5 Linux 网络及端口命令
linux·运维·服务器
零涂毕业设计16 小时前
毕业设计模块开发-OLED显示屏(IIC协议0.96寸)STM32 ESP32 FPGA Linux驱动免费分享
linux·stm32·单片机·嵌入式·esp32·fpga·oled
tedcloud12316 小时前
OmniRoute怎么部署?开源AI模型路由平台Linux部署教程
linux·服务器·人工智能·开源·音视频
霸道流氓气质16 小时前
KMS 密钥管理服务(Key Management Service)原理与实践
linux·服务器·数据库
SakitamaX16 小时前
LVS(Linux Virtual Server)概念详解
linux·运维·lvs
小张同学a.17 小时前
Linux系统管理
linux·运维
阿龙的工作记录17 小时前
深入理解Linux设备驱动模型
linux·嵌入式硬件·工作记录
代码村新手17 小时前
Linux的基本指令
linux·运维·服务器
hkj880818 小时前
Ubuntu 切换java版本
java·linux·ubuntu