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

进度条制作--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.dtcms.com/a/301591.html

相关文章:

  • 电商平台中,订单未支付过期,如何实现自动关单?
  • 字节前端面试知识点总结
  • 使用GIS中基于森林的分类与回归模型来估算房屋价值
  • c++17--std::variant
  • 决策树算法小结(上)
  • cmake入门学习
  • HCIE学习之路:路由引入
  • 嵌入式硬件篇---ESP32拓展板
  • C语言中 %zu 的用法
  • Javascript中的instanceof
  • VMware Workstation Pro虚拟机的下载和安装图文保姆级教程(附下载链接)
  • 点云的协方差矩阵的三个特征值代表什么?
  • 5.7 多处理器的基本概念 (答案见原书 P278)
  • 6、企业信息化
  • 大模型应用主要组成
  • 一、openEuler 安装git 详细操作步骤
  • 俄罗斯方块游戏开发(面向对象编程)
  • CPA青少年编程能力等级测评试卷及答案 Python编程(三级)
  • Go的defer和recover
  • Windows 11 安装 jdk 8
  • Cgroup 控制组学习(三)在容器中使用 CGroups
  • goland编写go语言导入自定义包出现: package xxx is not in GOROOT (/xxx/xxx) 的解决方案
  • 微服务架构面试题
  • PiscCode使用OpenCV实现漂浮方块特效
  • 编程语言Java——核心技术篇(五)IO流:数据洪流中的航道设计
  • 仓库管理系统-2-后端之基于继承基类的方式实现增删改查
  • 【RL第三篇】REINFORCE Leave-One-Out(RLOO)算法(基于留一法的REINFORCE策略梯度算法)
  • RK3568基于mpp实现硬解码(一):mpp库的编译使用
  • [每周一更]-(第151期):Go语言中的Map、Slice、Array和Hash原理详解
  • 博士招生 | 香港大学 招收人工智能和网络安全方向 博士生