初识Linux · 进度条

news2024/11/15 2:03:55

目录

前言:

1 缓冲区和回车换行

2 进度条


前言:

我们目前学习了些许知识,已经足够支持我们写一个非常非常小的项目了,即进度条,相信大家都有过下载游戏,等待游戏更新完成的时候,那么此时就有一个进度条,代表着游戏的更新进度,那么我们今天就来模拟实现这个过程,在此之前,我们需要一些预备知识。


1 缓冲区和回车换行

回车换行?是的,你没有看错,相信不少人对换行有一定的误解,我们在C语言里面使用的\n,代表的就是换行,换行之后,不少人发现光标都移动到下一行的最开始,所以不少人认为换行就是直接到下一行的开始,但是实际上并不是这样的,我们不妨看一下老式的键盘:

可以看到,回车是由一个L形状的,结合我们的语文作文,每次一行写满了,需要写下一行的时候,我们总是先定位到下一行,再回退到最开始,从当前位置定位到下一行的这个动作,就代表的是换行,从当前行的位置回退到最开始的位置的这个动作,就叫做回车,此时肯定有人会想到C语言的\r,代表的正是回车:

printf("%r",...);

当\n和\r在一起的时候,\n才是换行,其他时候都是回车换行,今天,我们学习的进度条的项目,就是使用的是\r这个占位符,即光标回退,执行覆盖的操作。

那么现在再来看看一段代码:

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 int main()
  4 {
  5   printf("Hello Linux!");                                                 
  6   sleep(1);
  7   return 0;
  8 }

这是在Linux中运行的一段代码,我们在Hello Linux!后面加\n和不加\n是有区别的,当我们没有\n,系统是先休眠一秒钟,然后打印Hello Linux!,但是我们如果在Hello Linux!后面加上了\n,就会先打印Hello Linux!,然后再进行休眠,这个现象不明显,但是可以引出比较重大的问题。

首先,缓冲区是什么?我们不妨将缓冲区认定为一块内存空间,在C++的学习中我们知道\n是刷新缓冲区的标志,所以,当我们没有加\n,printf先将字符串输入到缓冲区,然后等待刷新,此时没有刷新标志,所以系统执行sleep函数,休眠了1秒,此时程序结束,强制刷新缓冲区,所以现象是先休眠再打印,那么有了\n就同理,直接打印再休眠就完事了。

那么为什么强制刷新一定是在程序结束了再强制的呢?为什么不能提前强制刷新,当然是可以的,我们使用函数fflush即可:

我们可以看到参数是文件指针,那么我们去哪里找呢?

不要忘了,系统是默认打开了三个流,分别是stdin stdout stderror,文件输出流就是stdout,那么为什么是默认打开的?

因为早期的时候,发明编译器的人看到这么多人都有相同的需求,所以就有了后面的默认打开三个流。

那么此时代码就变成:

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 int main()
  4 {
  5   printf("Hello Linux!");
  6   fflush(stdout);                                                         
  7   sleep(1);
  8   return 0;
  9 }

现象就变成了先打印,然后再sleep,这就是强制刷新。

当然了,不用强制刷新想要验证缓冲区也很简单,我们只需要在Hello部分加上\n,看打印效果就可以了->打印效果就是先打印Hello然后再打印Linux。

有人就会提问了,为什么非要用\n来表示刷新标志呢?

\n刷新,简称行刷新,我们从缓冲区刷新到显示器文件上,要求的应该是少次数多数据量,最初的那批人结合了很多方面,觉得行刷新是最合适的,既要中和次数,也要考虑数据量的问题,所以选中了\n。


2 进度条

有了以上的基础,我们现在来实现一下进度条。

  1 #pragma once 
  2 #include <stdio.h>
  3 #include <string.h>
  4 #include <unistd.h>
  5 
  6 #define LENGTH 101
  7 #define style '='
  8 const char* lable = "|/-\\";
  9 
 10 void processbar()
 11 {
 12   char arr[LENGTH];
 13   memset(arr,'\0',sizeof(arr));
 14   int len = strlen(lable);
 15   int cnt = 0;
 16   while(cnt <= 100)
 17   {
 18     printf("[%-100s][%3d%%][%c]\r",arr,cnt,lable[cnt%len]);
 19     fflush(stdout);  // -> 不加导致卡顿
 20     arr[cnt++] = style;
 21     usleep(20000);
 22 
 23   }
 24   printf("\n"); // 不换行会导致命令提示符覆盖进度条                                                                                                                                                           
 25 }

本身代码是比较简单的,这里要注意两个点,一个是如果不强制刷新,也能达到我们想要的效果,但是是会等usleep休眠完了再打印,所以相对来说是有点卡顿的。

如果最后没有\n,就会导致命令提示符覆盖我们想要的进度条,从而导致覆盖,如:

上面的是正常的,下面的就是没有加,从而导致出现错误。

还有一个小点是要表达%需要加上两个%,就像两个\一样的,防止被转义了。

但是这个进度条版本并不逼真,总不可能什么东西都没有,咱们就干巴巴的来个进度条吧?

所以我们实现第二个版本,加点修饰什么的:

typedef void(*callback_t)(double,double);                                                            
void processbar(double total,double current)                                                        
{                                                                                                    
   char arr[LENGTH];                                                                                 
   memset(arr,'\0',sizeof(arr));                                                                     
   double rate = (current * 100.0) / total;                                                           
   int loop_rate = (int)rate;                                                                         
   int len = strlen(lable);                                                                           
   int cnt = 0;                                                                                       
   while(cnt <= loop_rate)                                                                            
   arr[cnt++] = style;                                                                              
   printf("[%-100s][%3.1lf%%][%c]\r",arr,rate,lable[cnt%len]);                                        
   fflush(stdout);                                                                                   }                                                                                                    

在进度条的头文件里面,我们稍加修饰,在主函数里面也一样:

  3 void Down_load(double filesize,callback_t cb)                                                                                                          
  4 {                                                                                                          
  5   double current = 0,bandtwidth = 1024*1024;                                                                                                                                                                  
  6   printf("Download begin...\n");                                                                                                          
  7   while(current <= filesize)                                                                                                          
  8   {                                                                                                          
  9     cb(filesize,current);                                                                                                          
 10     usleep(20000);                                                                                                          
 11     current += bandtwidth;                                                                                                          
 12   }                                                                                                          
 13   printf("Download done...\n");                                                                                                          
 14 } 

此时进度条的最简易版本就出来了。


感谢阅读!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电器维修系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;客服聊天管理&#xff0c;基础数据管理&#xff0c;公告管理&#xff0c;新闻信息管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;新闻信息&#xff0c;我的 开发系…

站长工具 API 接口,助力网站管理新高度

站长工具是一款非常实用的网站管理工具&#xff0c;通过其提供的API接口&#xff0c;可以轻松实现多种功能&#xff0c;如域名反查、域名备案查询、IPV6归属地查询等。这些功能可以帮助网站管理员更好地管理和优化自己的网站。以下是简单的代码示例&#xff0c;展示了如何使用站…

康姿百德公司官网柔压磁性枕豪华款高科技邂逅温柔夜活力满满!

康姿百德豪华柔压磁性枕慢回弹拥抱每寸肌肤&#xff0c;科技面料让呼吸自由夜夜好眠不是梦&#xff01; 现代家居设计不仅注重美观&#xff0c;更强调功能性和舒适性。康姿百德柔压磁性枕&#xff08;豪华款&#xff09;通过将高科技材料与创新设计结合&#xff0c;为我们的家…

Java反序列化漏洞-TemplatesImpl利用链分析

文章目录 一、前言二、正文1. 寻找利用链2. 构造POC2.1 生成字节码2.2 加载字节码1&#xff09;getTransletInstance2&#xff09;defineTransletClasses 2.3 创建实例 3. 完整POC 三、参考文章 一、前言 java.lang.ClassLoader#defineClass defineClass可以加载字节码&…

最大N个数与最小N个数的和

题目描述 给定一个数组&#xff0c;编写一个函数来计算它的最大N个数与最小N个数的和。你需要对数组进行去重 说明: 数组中数字范围[0&#xff0c;1000]最大N个数与最小N个数不能有重叠&#xff0c;如有重&#xff0c;输入非法返回-1输入非法返回-1 输入描述 第一行输入M&a…

uboot:配置编译

了解BSP 在嵌入式系统中&#xff0c;BSP&#xff08;Board Support Package&#xff09;被称为板级支持包或板级支持软件。它是一组针对特定硬件平台的软件支持包&#xff0c;为开发人员提供了一个统一的接口层&#xff0c;简化了硬件和软件之间的交互。BSP的主要功能和特点如…

Python数据分析-绘制图表

示例1&#xff1a; from pyecharts.charts import Bar # 柱状图 from pyecharts import options as optsfrom pyecharts.render import make_snapshotbar Bar() bar.add_xaxis([一月, 二月, 三月, 四月, 五月]) bar.add_yaxis("销售额", [10, 20, 15, 25, 30])# 配…

spring 事物使用场景说明

事务使用场景。 在某些业务场景下&#xff0c;如果一个请求中&#xff0c;需要同时写入多张表的数据。为了保证操作的原子性&#xff08;要么同时成功&#xff0c;要么同时失败&#xff09;&#xff0c;避免数据不一致的情况&#xff0c;我们一般都会用到spring事务。 确实&am…

使用Node-API进行异步任务开发

一、Node-API异步任务机制概述 Node-API异步任务开发主要用于执行耗时操作的场景中使用&#xff0c;以避免阻塞主线程&#xff0c;确保应用程序的性能和响应效率。 1、应用场景&#xff1a; 文件操作&#xff1a;读取大型文件或执行复杂的文件操作时&#xff0c;可以使用异步工…

TCP远程命令执行

目录 一. 命令集 二. 命令执行模块实现 三. 服务端模块实现 四. 服务端调用模块实现 五. 客户端模块实现 六. 效果展示 此篇教大家如何利用TCP进行远程命令执行。 一. 命令集 将值得信任的命令放进一个txt文件中&#xff0c;执行命令时&#xff0c;就去这…

英语每日一段 195

Promising economic indicators won’t instantly reverse the lingering impact of hard times for millions of families, workplace culture expert Jessica Kriegel said. “Perception and reality are sometimes aligned and sometimes not,” Kriegel told Newsweek. “…

这才是程序猿梦想的终端,赶快动手搞起来

文章目录 目标资源列表安装iTerm2安装oh-my-zsh安装颜色主题查找配置文件将配置内容复制到本地设置iTerm2 安装NERD FONTS下载字体安装设置iTerm2 安装PowerLevel10k修改.zshrc重新加载配置 安装插件下载[语法高亮](#syntaxhighlighting)下载[命令提示](#autosuggestions)配置插…

git的使用和gdb工具

1.git的使用 首先现在gitee上新建一个仓库 然后复制克隆链接到本地仓库 在本地仓库中&#xff0c;我们可以用git status查看仓库状态 我们要提交代码就是要三步 git add 文件名 git commit -m "写提交的日志" git push 将代码上传到远端仓库 然后你就完成一次提…

AIOT人工智能物联网六大场景

AIOT&#xff08;人工智能物联网&#xff09;融合了人工智能技术和物联网技术&#xff0c;实现了设备之间的智能互联和数据交互&#xff0c;在多个场景中都有广泛的应用。以下是一些主要的AIOT场景&#xff1a; 一、智能交通 智能汽车&#xff1a; 自动驾驶是AIOT在智能交通领…

tolower/toupper 函数讲解

目录 1.函数介绍 2.示例如下&#xff1a; 方源一把抓住VS2022&#xff0c;又是顷刻炼化&#xff01;&#xff1f; 1.函数介绍 C语言中提供了两种函数用于字符大小的转换 tolower可以将大写字符转小写字符&#xff0c;toupper可以将小写字符转大写字符 tolower函数与touppe…

设计并用Java实现一个简易的规则引擎

文章目录 前言正文一、代码结构二、核心代码2.1 上下文数据接口 ContextData.java2.2 规则接口 Rule.java2.3 规则引擎接口 RuleEngine.java2.4 规则引擎上下文类 RuleEngineContext.java2.5 规则引擎默认实现类 DefaultRuleEngine.java2.6 执行时出错监听器接口 ExecuteOnErro…

[mysql]SQL语言的规则和规范

规则 是什么呢&#xff0c;规则就是我们最基本&#xff0c;每时每刻都要遵守的比如人行道靠右&#xff0c;不能逆行&#xff0c; 规范 呢就是锦上添花&#xff0c;如果你不这么做&#xff0c;是不那么道德&#xff0c;不那么好的&#xff0c;就像小学生见到老师要问好&#…

【秋招笔试题】浇水

题解&#xff1a;离散化之后差分数组&#xff0c;注意左闭右闭区间的处理&#xff0c;将点和线段都抽象成点 #include <iostream> #include <vector> #include <set> #include <algorithm>using namespace std;const int MAXN 3000000 5; const int…

基于Spring Boot的火车订票管理系统

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;JAVA语言 Spring Boot框架 工具&#xff1a;IDEA/Eclipse、Navicat、Tomcat 系统展示 首页 管理…

方正畅享新闻采编系统 binary.do SQL注入漏洞分析复现

漏洞简介 binary.do接口的TableName参数对传入的数据没有充足的校验&#xff0c;导致该接口存在SQL注入漏洞&#xff0c;未授权的攻击者可获取数据库敏感信息。资产测绘搜索语句 hunter&#xff1a;web.body"/newsedit/newsedit/" 路由与鉴权分析 通过分析web.xml配置…