当前位置: 首页 > ds >正文

进度条制作--Linux知识的小应用

目录

一:回车与换行

二:缓冲区

三:显示器类型概念

四:进度条制作

4.1倒计时程序

​4.2进度条制作


一:回车与换行

回车:回到这一行的起点   \r

换行:换到下一行与该行相同的位置  \b

先回车再换行,可以达到在新的一行从头开始


二:缓冲区

\n:可以刷新缓冲区,把缓冲区的内容输出

根据上面的代码和运行结果可以看出,如果代码最后有\n,结果是先打印结果,然后睡眠2秒

如果代码最后没有\n,结果是先睡眠2秒,然后在打印结果,且最后没有换行

是\n,改变了代码执行顺序吗?

不,不管最后有没有\n,代码执行程序都是从上往下,先执行printf,再执行sleep,但是不带\n的现象感觉是先执行sleep,然后执行printf呢?如果都是先执行printf,那么不带\n的情况下,执行完的printf,原本该在显示器打印出来的字符串在哪里呢?----缓冲区

一种刷新是程序执行完,退出的时候,将缓冲区的内容一次性刷新到显示器中,这就是不带\n的时候,为什么先看到sleep的现象,再看到打印的字符串

另外一种就是\n,\n表示一种强制刷新,是行刷新,遇到\n会将缓冲区一行的内容刷新到显示器中

还有一种刷新方式就是fflush刷新

 

使用fflush就可以达成刷新缓冲区,但是不换行 

三:显示器类型概念

我们在定义的时候,a是int类型的,预料中打印应该是整数1234,结果也和预期是一样的
但是打印的是整数1234,还是1 2 3 4这四个字符,组合起来让我们以为是整数呢?

结论是:显示器没有类型概念,它在打印的时候是一个一个字符打印的

那为什么它的显示结果还和我们预想的一样呢?

四:进度条制作

4.1倒计时程序

根据上面的知识,我们可以实现一个小的倒计时程序,即在同一个行实现数字变换,从9->0

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

 如果使用上述代码执行,10->0呢?

此时会有一个新的问题,10在显示器来说是两个字符,但是9到0只是一个字符,此时就会出现,9到0,只会更换一个字符,另一个字符保持不变,如果要改变这种情况,就要把0~9变成两个字符

 4.2进度条制作

在知道倒计时程序的使用之后,可以进一步制作进度条,首先我们要明确进度条都需要哪些要素?

1.有一个进度框,框里面是进度条的移动,一般是一次性大小就固定不动

2.进度条随着进度的执行,在进度框里面向后移动

3.会显示当前进度的数字

4.有的时候进度数字后面还有一个交替变换的加载符号

根据上面的要素,以及前面的知识,可以写一个进度条代码:

process.h

#pragma once
#include <stdio.h>
#include <unistd.h>
#include <string.h>void Process();

process.c

#include "process.h"#define NUM 101
#define STYLE '='//效果[====>                           ]  [ ] [ ],最后>会消失
void Process()
{const char* lable = "|/-\\";int len = strlen(lable);char bar[NUM];memset(bar,'\0',sizeof(bar));int cnt = 0;while(cnt <= 100){printf("[%-100s][%d%%][%c]\r",bar,cnt,lable[cnt%len]);//进度条主体fflush(stdout);//刷新缓冲区,显示到显示器中bar[cnt] = STYLE;cnt++;//处理最后一个字符if(cnt == NUM){bar[cnt-1] = '\0';printf("[%-100s][%d%%][%c]\r",bar,cnt-1,lable[(cnt-1)%len]);//进度条主体break;}bar[cnt] = '>';usleep(50000);//unsleep单位是微秒,sleep单位是秒}
}

main.c 

#include<stdio.h>
#include "process.h"int main()
{Process();return 0;
}

Makefile:

process : process.c main.cgcc -std=c99 -o $@ $^.PHONY : clean
clean:rm -rf process

运行结果:

4.3进度条的场景应用

进度条一般用在下载量,动态刷新...

下面模拟一下进度条在下载量的实际应用:

process.h

#pragma once
#include <stdio.h>
#include <unistd.h>
#include <string.h>void FlushProcess();

process.c

#include "process.h"#define NUM 101
#define SPACE ' '
#define STYLE '='
#define POINT '.'
const int pnum = 3;void FlushProcess(double total, double current)
{//1.更新当前的百分比double rate = (current / total)*100;//2.更新当前的进度条char bar[NUM];//每1%更新一个进度条memset(bar,'\0',sizeof(bar));for(int i = 0; i < (int)rate;i++){bar[i] = STYLE;}//3.更新旋转光标,...的数量//为什么要加上旋转光标?//如果进度条缓慢,每次进入函数,取整之后进度条没有变化,此时可以通过旋转光标有无变化来判断程序是否在正常运行static int num = 0;num++;num %= pnum;char points[pnum+1];for(int i = 0; i < pnum;i++){if(i < num)points[i] = POINT;elsepoints[i] = SPACE;}//4.打印进度条printf("[%-100s][%.1lf%%]%s\r",bar,rate,points);fflush(stdout);
}

 main.c

#include<stdio.h>
#include "process.h"
#include<time.h>
#include <stdlib.h>typedef void(*flush_t) (double total,double current); //函数指针const int base = 20;//单词下载量的基础值
double total = 2048.0;//需要下载的量
double once = 0.1;//速度void download(flush_t f)
{double current = 0.0;while(current < total){//模拟下载行为int r = rand()%base+1;double speed = r * once;current += speed;if(current > total) current = total;usleep(10000);//更新本次下载量f(total,current);}printf("\n");
}int main()
{srand(time(NULL));download(FlushProcess);download(FlushProcess);download(FlushProcess);download(FlushProcess);return 0;
}

Makefile

process : process.c main.cgcc -std=c99 -o $@ $^.PHONY : clean
clean:rm -rf process

 运行结果:

 

http://www.xdnf.cn/news/16558.html

相关文章:

  • RabbiteMQ安装-ubuntu
  • Flutter实现列表功能
  • 【lucene】向量搜索底层文件关系梳理
  • git删除远程分支和本地分支
  • WPFC#超市管理系统(2)顾客管理、供应商管理、用户管理
  • docker 自定义网桥作用
  • macOS 安装 Homebrew
  • Vue基础(25)_组件与Vue的内置关系(原型链)
  • 「iOS」————消息传递和消息转发
  • K8S 九 安全认证 TLS
  • 深入理解现代前端开发中的 <script type=“module“> 与构建工具实践
  • Orange的运维学习日记--13.Linux服务管理
  • OpenLayers 综合案例-点位聚合
  • 【通识】线性代数(Linear Algebra)
  • 深度学习在计算机视觉中的应用:对象检测
  • 从 .NET Framework 到 .NET 8:跨平台融合史诗与生态演进全景
  • 设计模式(十一)结构型:外观模式详解
  • ESP32步进电机控制实战:从原理到代码实现
  • JAVA秋招学习指南
  • 【Java实例】服务器IP一站式管理
  • linux 部署 flink 1.15.1 并提交作业
  • ios UIAppearance 协议
  • 元宇宙背景下治理模式:自治的乌托邦
  • 移植pbrt中的并行化到ray trace in weeks中
  • 268. 丢失的数字
  • RocksDB跳表MemTable优化揭秘
  • Java 集合进阶:从 Collection 接口到迭代器的实战指南
  • Containerd简介
  • 栈算法之【有效括号】
  • mybatis-plus从入门到入土(三):持久层接口之IService