目录

\r 、\n、fflush

倒计时

进度条

进度条进阶版

结语


\r 、\n、fflush

首先我们先来认识这三个东西,这将会是我们接下来两个小程序的重点之一

首先是我们的老演员\n,也就是回车加换行

这里面其实包含了两个操作,一个叫做回车,一个叫做换行

而单纯的回车就是指,我们现在的光标,回到当前行的最前面

而换行 + 回车就是来到下一行的最前面

而我们的 \r 就是单纯的回车,回到当前行的最前面

但是我们还有一个缓冲区的概念

也就是,当我们使用了\n之后就会自动刷新缓冲区,但是\r不会

我们不想用\n是因为不想出现下面这样的情况:

所以我们只想回到第一行然后从头开始覆盖式地进行写入

但是如果是\r的话,就会出现一个情况就是,我们会等到程序结束之后才会把最后一次的结果打印出来,这时因为缓冲区不会因为\r刷新

所以我们这时候就需要fflush(stdout),这样就能在不回车的前提下达到提前刷新缓冲区的效果了

至于stdout,这就是系统默认打开的标准输出文件,其实我们这里可以粗浅的看作就是显示器,我们需要刷新缓冲区才能让显示器上显示结果

倒计时

至于倒计时,其实相当简单,我们只需要知道,这是在不停地打印数字,并且会在同一个位置打印,这就需要用到回车(\r)回到最前面,然后覆盖掉前面的结果以达到原地变化的效果

但是由于\r不会刷新缓冲区,所以我们就需要使用fflush刷新,这样,我们的倒计时就写好了

代码如下:

void time_count_down(int total)
{int cnt = total;while(cnt >= 0){printf("倒计时: %2d\r", cnt);fflush(stdout);cnt--;usleep(300000);}printf("\n");
}

进度条

首先,我们需要知道的是,进度条的本质和倒计时是一样的,就是\r移动光标,通过覆盖式写入达到变化的效果

我们先来看看成品的样子:

分析一下,首先我们需要预留出一百个空间,表现出递进的效果

这一步我们可以直接建一个数组,然后一个循环,每循环一次,就打印出当前数组里面的内容,并且在当前数组最后一个 “ = ” 后面再加一个等号,这样,我们就达到了循环递进的效果

但是,我们需要注意的是,这期间我们需要一直使用 \r 和 fflush,如下:

#define LENGTH 101
#define STYLE '='void ProcessBar()
{char bar[LENGTH];memset(bar, '\0', sizeof bar);int cnt = 0;while(cnt <= 100){printf("[%-100s]\r", bar);fflush(stdout);bar[cnt++] = STYLE;usleep(10000);}printf("\n");
}

注意,上面的 “%-100d” 中,100就代表默认留出100个位置,-100则代表左对齐

接着,我们可以看到,进度条后面还有两个东西:

这两个,一个是实时显示当前加载进度的数字显示,还有一个是想通过 |/-\ 这四个字符,达成一条线在不停旋转的动态效果,也就是在提醒用户,可能用户看到进度条不动了以为是网卡了,但其实还在下载,只是进度比较慢,暂时卡住了而已,动态的话就是为了避免这个问题

首先来解决第一个

这个其实我们只需要把数字填进去就可以了,只是后面的%需要写两个而已,写一个显示不出来

而最后一个就是,我们先写一个数组:

const char* label = "|/-\\";

我们只需要不停的从左往右选择即可,但是由于会越界,所以我们就需要%一个数组大小,这样才不会越界

而其中 \\ 有两个是因为只写一个不显示

比如,我现在数组大小是4,如果当前数字大小是4,4%4 = 0,那么就会直接回到第一个数组下标位置,5%4就是1,代表第二个位置,依此类推

总代码如下:

#define LENGTH 101
#define STYLE '='
const char* label = "|/-\\";void ProcessBar()
{char bar[LENGTH];memset(bar, '\0', sizeof bar);int len = strlen(label);int cnt = 0;while(cnt <= 100){printf("[%-100s][%3d%%][%c]\r", bar, cnt, label[cnt % len]);fflush(stdout);bar[cnt++] = STYLE;usleep(10000);}printf("\n");
}

进度条进阶版

现实中,我们的进度条都是搭配了任务一起的

比如我们可以写一个下载的任务,影响下载的因素这里假设只有带宽,他就相当于下载速度吧在这里

然后我们只需要提供一个文件总大小,模拟这个过程即可

代码如下(模拟下载任务的代码):

#define bandwidth 1024*1024*1.0;void download(double file_size)
{double current = 0.0;while(current <= file_size){//调用进度条ProcessBar(file_size, current);current += bandwidth;usleep(20000);}printf("\n");
}

这时候我们的进度条文件就需要更改一下了

由于会被频繁调用,所以我们的进度条在这里,每一次调用都代表那一瞬间的状态

所以我们在进度条那里的循环可以只是循环添加 =

接着,我们的进度这次就是按照百分比来算的了

所以进度条需要一个总的文件大小,以及现在文件加载到哪里了,这样我们将两个文件除出来之后再乘100,就是当前文件加载的百分比进度:

double rate = current*100.0/total;

接下来的都是小小修改一下而已,代码如下:

#define LENGTH 101
#define STYLE '='
const char* label = "|/-\\";void ProcessBar(double total, double current)
{char bar[LENGTH];memset(bar, '\0', sizeof bar);int len = strlen(label);double rate = current*100.0/total;int loop_count = (int)rate;int cnt = 0;while(cnt <= loop_count){bar[cnt++] = STYLE;}printf("[%-100s][%.1lf%%][%c]\r", bar, rate, label[cnt % len]);fflush(stdout);
}

最后,我们还可以再来一个小优化

试想一下,我们以后如果有了图形化界面,或者就是单纯更好的进度条,对于这个下载任务而言,如果我们只是用一个函数指针的话,到时候我们只需要修改指针即可,这样的话,修改起来就很方便,当我们有了更好的进度条的时候

如下,我们可以先在 .h 文件里面定义一个函数指针:

typedef void (*pb)(double, double);

接着,我们的下载任务里面,就可以直接加上这个参数了:

#define bandwidth 1024*1024*1.0;void download(double file_size, pb procbar)
{double current = 0.0;while(current <= file_size){procbar(file_size, current);current += bandwidth;usleep(20000);}printf("\n");
}int main()
{download(100.0*1024*1024, ProcessBar);return 0;
}

结语

这篇文章到这里就结束啦!!~( ̄▽ ̄)~*

如果觉得对你有帮助的,可以多多关注一下喔

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/907361.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/907361.shtml
英文地址,请注明出处:http://en.pswp.cn/news/907361.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从零实现wss通信示例(WebSocket SSL)

客户端和服务端代码框架跟上一篇一致,仅增加了ssl的证书部分用于加密通信,明文通信(ws协议)见上一篇【https://blog.csdn.net/suoxd123/article/details/148093934】 1. 证书创建 1. 安装openssl 【官网地址】:https://slproweb.com/products/Win32OpenSSL.html 1.2 …

mysql 索引失效有哪些

InnoDB存储引擎根据索引类型不同&#xff0c;分为聚簇索引和二级索引 聚簇索引&#xff1a;叶子节点存放的是实际数据 二级索引&#xff1a;存放的是主键值&#xff0c;不是实际数据 1.对索引使用左或者左右模糊匹配 select * from t_user where name like %林‘&#xff1b…

LabVIEW通用测控平台设计

基于 LabVIEW 图形化编程环境&#xff0c;设计了一套适用于工业自动化、科研测试领域的通用测控平台。通过整合研华、NI等品牌硬件&#xff0c;实现多类型数据采集、实时控制及可视化管理。平台采用模块化架构&#xff0c;支持硬件灵活扩展&#xff0c;解决了传统测控系统开发周…

华为OD机试真题——智能驾驶(2025A卷:200分)Java/python/JavaScript/C/C++/GO最佳实现

2025 A卷 200分 题型 本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式; 并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析; 本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分…

速卖通,国际站测评补单,如何平衡效率和安全

测评能够帮助卖家让平台更喜欢自己的产品&#xff0c;给予更好排名的同时也让后续进入店铺的买家更容易认可自己的产品。这是进行真实交易后形成的评价&#xff0c;而不是通过机器软件生成&#xff0c;形成虚拟数据后&#xff0c;那种刷评形式产生的评论。它符合任何电商平台的…

学习路之PHP--easyswoole3.3入门及文件热加载

学习路之PHP--easyswoole入门 一、框架说明二、常用命令三、文件热加载 一、框架说明 目录结构 目录结构 project 项目部署目录 ├─App 应用目录(可以有多个) │ ├─HttpController 控制器目录 │ │ └─Index.php …

设计模式26——解释器模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用&#xff0c;主要是下面的UML图可以起到大作用&#xff0c;在你学习过一遍以后可能会遗忘&#xff0c;忘记了不要紧&#xff0c;只要看一眼UML图就能想起来了。同时也请大家多多指教。 解释器模式&#xff08;Interp…

第三届宁波技能大赛网络安全赛项样题

2025 第三届宁波技能大赛网络安全赛项样题 模块A: 网络安全事件响应、数字取证调查和应用安全任务一:应急响应任务二:操作系统取证任务三:网络数据包分析任务四:代码审计 模块B:CTF 夺旗-攻击模块C:CTF 夺旗-防御需要环境培训可以私信博主&#xff01;&#xff01;&#xff01;…

GO语言进阶:掌握进程OS操作与高效编码数据转换

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…

IO进程(进程 Process)

什么是进程&#xff1f; 1.概念 程序&#xff1a;编译好的可执行文件&#xff0c;存放在磁盘上的指令和数据的有序集合。 由此可见程序是静态的&#xff0c;没有执行的概念。 进程&#xff1a;是程序的一次执行的过程&#xff0c;是一个可调度的任务&#xff0c;也是执行一…

CSS传统布局与定位详解与TDK三大标签SEO优化

一、传统布局基础 1. 文档流布局 浏览器默认的文档流布局方式遵循以下规则&#xff1a; 块级元素&#xff08;如<div>、<p>、<h1>&#xff09;&#xff1a; 独占一行宽度默认100%可以设置宽高、内外边距 div {width: 500px;height: 200px;margin: 10px …

【GraphQL】深入解析 Apollo Client:从架构到实践的一站式 GraphQL 解决方案

深入解析 Apollo Client&#xff1a;从架构到实践的一站式 GraphQL 解决方案 1. 引言 GraphQL 作为现代 API 开发的核心技术&#xff0c;其灵活性和高效性正在重塑数据交互模式。Apollo Client 作为 GraphQL 生态中最受欢迎的客户端库&#xff0c;凭借强大的缓存机制、框架集…

docker学习基本使用教程

docker是一款用于开发部署和运行容器化平台&#xff0c;能将应用及其依赖打包成轻量级、可移植的容器&#xff0c;实现一次构建&#xff0c;随处运行。docker是cs架构程序&#xff08;客户端和服务端&#xff09;&#xff0c;docker客户端向docker守护进程发送请求&#xff0c;…

万字详解RTR RTSP SDP RTCP

目录 1 RTSP1.1 RTSP基本简介1.2 RSTP架构1.3 重点内容分析 2 RTR2.1 RTR简介2.2 RTP 封装 H.2642.3 RTP 解封装 H.2642.4 RTP封装 AAC2.5 RTP解封装AAC 3 SDP3.1 基础概念3.2 SDP协议示例解析3.3 重点知识 4 RTCP4.1 RTCP基础概念4.2 重点 5 总结 1 RTSP 1.1 RTSP基本简介 一…

唯一原生适配鸿蒙电脑的远程控制应用,向日葵正式上线

近日&#xff0c;华为正式发布鸿蒙电脑新品&#xff0c;标志着HarmonyOS在PC端生态的进一步拓展。作为远程控制领域的先行者&#xff0c;贝锐科技旗下的向日葵远程控制软件也在第一时间完成了对鸿蒙电脑系统的原生适配&#xff0c;并已正式上线华为鸿蒙电脑应用市场&#xff0c…

vue2中,codemirror编辑器的使用

交互说明 在编辑器中输入{时&#xff0c;会自动弹出选项弹窗&#xff0c;然后可以选值插入。 代码 父组件 <variable-editorv-model"content":variables"variables"placeholder"请输入模板内容..."blur"handleBlur" />data…

Kafka自定义分区策略实战避坑指南

文章目录 概要代码示例小结 概要 kafka生产者发送消息默认根据总分区数和设置的key计算哈希取余数&#xff0c;key不变就默认存放在一个分区&#xff0c;没有key则随机数分区&#xff0c;明显默认的是最不好用的&#xff0c;那kafka也提供了一个轮询分区策略&#xff0c;我自己…

WPF 全屏显示实现(无标题栏按钮 + 自定义退出按钮)

WPF 全屏显示实现&#xff08;无标题栏按钮 自定义退出按钮&#xff09; 完整实现代码 MainWindow.xaml <Window x:Class"FullScreenApp.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas…

sqli_labs第二十九/三十/三十一关——hpp注入

一&#xff1a;HTTP参数污染&#xff1a; hpp&#xff08;http parameter pollution)注入中&#xff0c;可以通过在hppt的请求中注入多个同名参数来绕过安全过滤 原理&#xff1a;php默认只取最后一个同名参数 比如在这一关里&#xff0c;可能对第一个id参数进行消毒处理&a…

【STM32】按键控制LED 光敏传感器控制蜂鸣器

&#x1f50e;【博主简介】&#x1f50e; &#x1f3c5;CSDN博客专家 &#x1f3c5;2021年博客之星物联网与嵌入式开发TOP5 &#x1f3c5;2022年博客之星物联网与嵌入式开发TOP4 &#x1f3c5;2021年2022年C站百大博主 &#x1f3c5;华为云开发…