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

【Linux】使用Linux实现小程序 - 进度条

在这里插入图片描述

目录

  • 一、缓冲区
  • 二、回车换行的概念
  • 三、进度条的设计
    • 3.1 版本1(没有配合场景)
    • 3.2 版本2(配合场景)
    • 3.3 版本3(美化进度条)
  • 结尾

一、缓冲区

C/C++语言,会针对标准输出,给我们提供默认的缓冲区,这里主要讲输出缓冲区,那么它在哪里呢?

在C语言中,输出缓冲区通常与标准I/O流(如stdout、stderr等)相关联。这些流在C标准库中通过FILE结构体来表示,而FILE结构体内部封装了文件描述符和缓冲区等信息。因此,当使用printf()等函数进行输出时,实际上是将数据写入到了与stdout流相关联的缓冲区中。

在这里插入图片描述
那么需要怎么证明呢?

当我们没有使用fflush刷新缓冲区时,printf()函数早已运行了,但是数据却没有立马显示出来,而是暂停了两秒钟才显示出来,因为printf()函数输出的数据在缓冲区中,所以没有立马显示出来,当暂停两秒钟后,程序结束,强制刷新缓冲区,才将缓冲区的内容输出。
在这里插入图片描述

那么有人也会问了,当我们使用 printf()函数输出数据时添加\n,也能立马输出数据这是为什么?
因为/n也是一种刷新策略,/n也叫做行刷新。


二、回车换行的概念

在这里向大家提一个问题,大家是否认为回车和换行是一个东西,其实不然,回车和换行是两个不同的概念,回车是将光标移回当前行的第一个位置,换行是将光标的位置移动到下一行,但光标的位置并不会移回行的第一个位置
在这里插入图片描述
在老式键盘中的回车换行也是比较形象的体现了回车和换行的特征。
在这里插入图片描述

那么我们在敲代码使用的 /r/n 分别是什么呢?
- /r 是回车,光标仅仅回到当前行的第一个位置。
- /n 是回车换行,光标即移回行的第一个位置,又移动到下一行。

在这里插入图片描述

那么下面写一份代码,除/r/n不同外其他部分全部相同,来看看程序的结果分别是什么。

在这里插入图片描述

在这里插入图片描述

我们通过上面的图片可以看到使用/n时,每一秒钟在下一行输出一个数字

而使用/r时,每一秒钟在当前行输出一个数字,并且覆盖上一个字符,最终被命令行覆盖,但是当循环时强制刷新缓冲区就可以把最后一个数字留下来,通过/r的这个特性,那么我们就可以设计倒计时,进度等。


三、进度条的设计

3.1 版本1(没有配合场景)

在这里插入图片描述

进度条效果图

在这里插入图片描述

// 	process.c
#include"process.h"                                                                                                                         const char rotate[]={"|/-\\"};    void process()    
{    char arr[SIZE] = {0};    int rate = 0;    int len = strlen(rotate);    while(rate <= MAX_RATE)    {    printf("[%-100s][%3d%%][%c]\r",arr,rate,rotate[rate%len]);    usleep(STIME);    arr[rate++]=STYLE;    }    printf("\n");    
}
//	process.h
#include<stdio.h>
#include <unistd.h>
#include<string.h>#define STYLE '#'      // 进度条的风格
#define MAX_RATE 100   // 进度的最大值
#define SIZE 101       // 数组需要开多大 
#define STIME 1000*50  // 暂停的时间void process();
//	main.c
#include"process.h"int main()
{process();return 0;                                                                                                                           }
// 	Makefile
cc=gcc
src=main.c process.c                                                                                                                    
target=myprocess$(target):$(src)$(cc) $^ -o $@.PHONY:clean
clean:rm -f $(target)

3.2 版本2(配合场景)

无论任何进度条,一定和某种任务关联,那么这个版本的进度条不是在函数内部循环打印,而是通过回调的方式来进行某种任务的通知,动态进行更新进度条。

在这里插入图片描述

// 	process.c
#include"process.h"                                                                                                                         const char rotate[]={"|/-\\"};      void process2(int rate)      
{      static char arr[SIZE] = {0};      int len = strlen(rotate);      if(rate <= MAX_RATE && rate >= 0)      {      printf("[%-100s][%3d%%][%c]\r",arr,rate,rotate[rate%len]);  fflush(stdout);  arr[rate]=STYLE;          }      
}      
// main.c
#include"process.h"    #define TOTAL_SIZE 1024*1024  // 程序大小    
#define DSIZE 1024*10 // 下载速度                                                                                                           void download()    
{    int target = TOTAL_SIZE;    int sum = 0;  // 当前下载总大小    while(sum <= TOTAL_SIZE)    {    int rate = sum*100/target;    process2(rate);    sum += DSIZE;    usleep(STIME);    }    process2(MAX_RATE);    printf("\n");    
}    int main()    
{    download();    return 0;    
} 
//	process.h
#include<stdio.h>    
#include <unistd.h>    
#include<string.h>    #define STYLE '#'      // 进度条的风格    
#define MAX_RATE 100   // 进度的最大值    
#define SIZE 101       // 数组需要开多大                                                                                                    
#define STIME 1000*50  // 暂停的时间    typedef void(*callback_t)(int);    void process1();    
void process2(int); 

3.3 版本3(美化进度条)

上面两个版本进度条中的旋转光标会受到进度的影响,在生活中下载软件、游戏等应用的时候可能在某个进度的时候突然卡住了,如果旋转光标会受到进度的影响的话,就不能知道软件是否在下载,所以当前版本对当前问题进行了优化,使旋转光标不再受到进度的影响。并且将进度的显示修改为小数。
在这里插入图片描述

进度条效果图

在这里插入图片描述

#include"process.h"    const char rotate[]={"|/-\\"};    void process3(double rate)    
{    static int rotate_cnt = 0;    static char arr[SIZE] = {0};    int len = strlen(rotate);    rotate_cnt = ++rotate_cnt % len;    if(rate < MAX_RATE && rate > 0)    {    arr[(int)rate-1]=STYLE_BODY;    arr[(int)rate]=STYLE_HEAD;    }    else if(rate == MAX_RATE)                                                                                                               {    arr[(int)rate]='\0';    arr[(int)rate-1]=STYLE_BODY;    }    printf("[%-100s][%6.2lf%%][%c]\r",arr,rate,rotate[rotate_cnt%len]);    fflush(stdout);    
} 
//	main.c
#include"process.h"                                                                                                                         #define TOTAL_SIZE 1024*1024  // 程序大小    
#define DSIZE 1024*10 // 下载速度    void download(callback_t cb)    
{    int target = TOTAL_SIZE;    int sum = 0;  // 当前下载总大小    while(sum <= TOTAL_SIZE)    {    double rate = sum*100.0/target;    cb(rate);    sum += DSIZE;    usleep(STIME);    }    cb(MAX_RATE);    printf("\n");    
}    int main()    
{    download(process3) ;    return 0;    
}  
// 	process.h
#include<stdio.h>                                                                                                                           
#include <unistd.h>    
#include<string.h>    #define STYLE '#'      // 进度条的风格    
#define MAX_RATE 100   // 进度的最大值    
#define SIZE 101       // 数组需要开多大     
#define STIME 1000*50  // 暂停的时间    
#define STYLE_HEAD '>'    
#define STYLE_BODY '='    // typedef void(*callback_t)(int);    
typedef void(*callback_t)(double);    void process1();    
void process2(int);    
void process3(double); 

结尾

如果有什么建议和疑问,或是有什么错误,大家可以在评论区中提出。
希望大家以后也能和我一起进步!!🌹🌹
如果这篇文章对你有用的话,希望大家给一个三连支持一下!!🌹🌹

在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 计算机网络:URL构成
  • tcp 流量控制
  • Zabbix结合Grafana
  • 【进程间通信】共享内存
  • 冒泡法排序:本题要求将给定的n个整数从小到大排序后输出。输出时相邻数字中间用一个空格分开,行末不得有多余空格。
  • 【QT】学习笔记:枚举桌面窗口句柄
  • Kafka【三】Windows下安装Kafka集群
  • 使用VM创建centos7环境
  • 淘宝扭蛋机小程序开发,吸引更多的消费者
  • 海外媒体发布:12个旅游业发展媒体宣发对策,给你提升曝光量
  • 解决el-table中使用el-input无法聚焦问题
  • 加速产品研发:项目管理软件与团队的协同之道
  • easy_fastapi Python 后端开发框架
  • Python 与 Excel 图表自动化:让数据“会说话”
  • 使用Qdrant + CNCLIP + Gradio 实现图文检索
  • ES6--对象的扩展
  • ES6简单总结(搭配简单的讲解和小案例)
  • Java知识点总结(JavaIO-打印流)
  • java中的hashCode
  • js ES6 求数组的交集,并集,还有差集
  • Mocha测试初探
  • Nodejs和JavaWeb协助开发
  • React 快速上手 - 06 容器组件、展示组件、操作组件
  • Vue 重置组件到初始状态
  • 创建一个Struts2项目maven 方式
  • 番外篇1:在Windows环境下安装JDK
  • 简单实现一个textarea自适应高度
  • 简单数学运算程序(不定期更新)
  • 腾讯大梁:DevOps最后一棒,有效构建海量运营的持续反馈能力
  • scrapy中间件源码分析及常用中间件大全
  • # Panda3d 碰撞检测系统介绍
  • #mysql 8.0 踩坑日记
  • #NOIP 2014# day.1 T3 飞扬的小鸟 bird
  • #调用传感器数据_Flink使用函数之监控传感器温度上升提醒
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (04)Hive的相关概念——order by 、sort by、distribute by 、cluster by
  • (C语言)输入自定义个数的整数,打印出最大值和最小值
  • (day 12)JavaScript学习笔记(数组3)
  • (MTK)java文件添加简单接口并配置相应的SELinux avc 权限笔记2
  • (多级缓存)缓存同步
  • (二)Eureka服务搭建,服务注册,服务发现
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (附源码)springboot家庭财务分析系统 毕业设计641323
  • (十二)python网络爬虫(理论+实战)——实战:使用BeautfulSoup解析baidu热搜新闻数据
  • (四)TensorRT | 基于 GPU 端的 Python 推理
  • (算法)求1到1亿间的质数或素数
  • (转)IIS6 ASP 0251超过响应缓冲区限制错误的解决方法
  • (转)平衡树
  • .aanva
  • .L0CK3D来袭:如何保护您的数据免受致命攻击
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .NET 常见的偏门问题
  • .net通过类组装数据转换为json并且传递给对方接口
  • @ConditionalOnProperty注解使用说明
  • @JsonFormat与@DateTimeFormat注解的使用