『Linux升级路』进度条小程序

🔥博客主页:小王又困了

📚系列专栏:Linux

🌟人之为学,不日近则日退

❤️感谢大家点赞👍收藏⭐评论✍️


目录

一、预备知识

📒1.1缓冲区

📒1.2回车和换行

二、倒计时

📒2.1源代码

📒2.2注意事项

三、进度条

📒3.1源代码

📒3.2实际应用


一、预备知识

📒1.1缓冲区

我们先观察两段代码的现象:

#include <stdio.h>
#include <unistd.h>
int main() 
{printf("Hello Linux!\n");                                                                                                                                                   sleep(3);return 0;
}

 这段代码先执行printf函数,在屏幕上打印出Hellow Linux!,然后执行sleep函数让函数休眠3秒,最后程序结束。

#include <stdio.h>
#include <unistd.h>
int main() 
{printf("Hello Linux!");                                                                                                                                                   sleep(3);return 0;
}

 通过上图我们可以看到,当我们去掉 ‘\n’ 对代码进行编译,程序先休眠了3秒,然后在屏幕上打印Hellow Linux!。由于去掉了‘\n’ ,也没有换行。

📝现象分析:

      看到上面的现象,大家一定会有很大的疑惑。难道程序是先执行了sleep函数,然后再去执行printf函数。这样的猜想是错误的,任何一个C语言程序,没有遇到选择和循环语句,都要严格按照顺序结构去执行,代码都是从上到下依次执行。所以一定是先执行printf函数,再执行sleep函数。那在休眠的3秒里,Hellow Linux!去了哪里呢?代码被保存在了缓冲区中,默认当程序结束的时候才会将缓冲区中的内容刷新出来,带 \n 就是要求把缓冲区的的数据立即刷新到显示器上。

  • 缓冲区是一种用于临时存储数据的区域,通常用于临时保存数据以平衡数据处理速度不匹配的情况。 

📒1.2回车和换行

     回车和换行是两个与文本文件和文本编辑有关的控制字符,它们在不同的操作系统和编程环境中可能有不同的表现。

📝回车:将光标移动到当前行的开始(最左侧)

  • 表示为ASCII字符 \r
  • 在打字机时代,回车的原意是将打印头移动到行首,以便在同一行上写入新的文本。
  • 在计算机中,回车通常表示将光标移动到当前行的开头,但不换行到新的一行。

📝换行:将光标水平方向保持不变,竖直方向向下平移一行。

  • 表示为ASCII字符 \n
  • 在打字机时代,换行的原意是将纸向上移动一行,以便在新的行上写入文本。
  • 在计算机中,换行通常表示将光标移动到下一行的开头。

二、倒计时

📒2.1源代码

 学习了上面的知识,我们可以写一个倒计时的小程序。

📖源代码

#include <stdio.h>
#include <unistd.h>int main()
{int cnt=9;while(cnt>=0){printf("%d\r",cnt);sleep(1);cnt--;}printf("\n");return 0;
}

📖效果演示

如上图,运行我们的程序,却没有想要的倒计时效果,这是因为我们没有刷新缓冲区,执行的结果都存放在缓冲区 。我们要使用fflush接口来刷新缓存区。

📝刷新缓冲区

任何一个C程序运行的时候都会默认帮我们打开以下三个流:

  • stdin —— 标准输入流(键盘)
  • stdout —— 标准输出流(显示器)
  • stderr —— 标准错误(显示器)

这三个流都是FILE*的指针,所以任何一个C程序运行的时候,操作系统会帮我们打开以上三个文件。我们只需要看stdout标准输出流,使用fflush接口刷新。

📖源代码

#include <stdio.h>
#include <unistd.h>
int main()
{int cnt = 9;while(cnt >= 0){printf("%-2d\r",cnt);fflush(stdout);sleep(1);cnt--;} printf("\n");                                                                                                                                                                         return 0;
}

 📖效果演示

📒2.2注意事项

📝格式化控制

     我们需要知道,往显示器上打印整型10,本质上是打印了字符1和字符0。因此打印10,会占用两个字符,而打印0~9只需要一个字符,所以 \r 回车之后只会覆盖一个字符,对第二个字符0始终没有影响,因此我们需要用%-2d来控制,每次打印两个位宽的字符, - 表示将这两个字符左对齐。如果不进行格式化控制,打印出来的结果将是下面这样:

三、进度条

📒3.1源代码

     我们实现的进度条进度条除了有进度的推进,还要有百分比提示和转动提示。

📖processBar.h

#pragma once
#include <stdio.h>
#include <unistd.h>
#include <string.h>#define NUM 103
#define BODY '='
#define HEAD '>'  void processbar();

📖processBar.c

#include "processbar.h"//引用头文件
const char* lable = "|/-\\";//转动提示
void processbar()
{char bar[NUM];int cnt=0;memset(bar,'\0',sizeof(bar));int len=strlen(lable);bar[cnt]=HEAD;while(cnt<=100){printf("[%-100s][%d%%][%c]\r",bar,cnt,lable[cnt%len]);fflush(stdout);bar[cnt++]=BODY;if(cnt<100){bar[cnt]=HEAD;                                                                                                                                }usleep(100000);}printf("\n");
}

📒3.2实际应用

     上面的代码只是演示进度条的原理,但是在实际中,进度条并不是这样用的。以下载东西为例,作为一个进度条,它本身并不知道下载了多少,它只会提供一个接口,在下载东西的时候,调用这个接口,然后将已经下载好的比率作为参数传给进度条模块,它会根据比率打印出对应的进度条样式。

📖processBar.h

#pragma once
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>#define NUM 103
#define BODY '='
#define HEAD '>'  typedef void (*callback_t)(double);void process_flush(double rate);

📖processBar.c

#include "processbar.h"//引用头文件
const char* lable = "|/-\\";//转动提示char buffer[NUM] = {0};
void process_flush(double rate)
{static int cnt = 0;int n = strlen(lable);if(rate <= 1.0) buffer[0] = Head;printf("[\033[4;32;44m%-100s\033[0m][%.1f%%][%c]\r", buffer, rate, lable[cnt%n]);fflush(stdout);buffer[(int)rate] = Body;if((int)rate+1 < 100) buffer[(int)(rate+1)] = Head;if(rate>=100.0) printf("\n");cnt++;cnt%=n;
}

📖main.c

void download(callback_t cb) // 回调函数的形式
{srand(time(NULL)^1023);int total = FILESIZE;while(total){usleep(10000); //下载动作int one = rand()%(1024*1024*10);total -= one;if(total < 0) total = 0;// 当前的进度是多少?int download = FILESIZE - total;double rate = (download*1.0/(FILESIZE))*100.0; // 0 23.4 35.6, 56.6cb(rate);//process_flush(rate);//printf("download: %f\n", rate); // rate出来了,应该让进度条刷新}
}int main()
{download(process_flush);return 0;
}


🎁结语: 

     本次的内容到这里就结束啦。希望大家阅读完可以有所收获,同时也感谢各位读者三连支持。文章有问题可以在评论区留言,博主一定认真认真修改,以后写出更好的文章。你们的支持就是博主最大的动力。

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

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

相关文章

修改正点原子综合实验的NES模拟器按键控制加横屏

​​​​​​​ 开发板&#xff1a;stm32f407探索者开发板V2 屏幕是4.3寸-800-480-MCU屏 手头没有V3开发板&#xff0c;只有V2&#xff0c;所以没法测试 所以只讲修改哪里&#xff0c;请自行修改 先改手柄部分&#xff0c;把手柄改成按键 找到左边的nes文件夹中的nes_mai…

采用轨到轨输出设计 LTC6363HMS8-2、LTC6363HMS8-1、LTC6363HRD、LTC6363IDCB差分放大器I

产品详情 LTC6363 系列包括四个全差分、低功耗、低噪声放大器&#xff0c;具有经优化的轨到轨输出以驱动 SAR ADC。LTC6363 是一款独立的差分放大器&#xff0c;通常使用四个外部电阻设置其增益。LTC6363-0.5、LTC6363-1 和 LTC6363-2 都有内部匹配电阻&#xff0c;可分别创建…

【Python百宝箱】代码冲突?文件合并不再是问题!Python解决方案大揭秘

Python脚本与图形工具&#xff1a;文件比较与合并的完整指南 前言 在软件开发、版本控制和数据处理领域&#xff0c;文件比较和合并是至关重要的任务。Python生态系统中涌现了许多强大的工具和库&#xff0c;为开发者提供了丰富的选择。本指南将深入探讨 Python 中常用的文件…

看完了一个动画电影-心灵奇旅

refer: 开二倍速看完了&#xff0c;一部分是听的&#xff0c;剧情还可以&#xff0c;就是普通的治愈片。 里边有个台词&#xff1a; 一条小鱼游到一条老鱼旁边说,“我要找到他们称之为海洋的东西。” “海洋?”老鱼问,“你现在就在海洋里啊。” “这儿?”小鱼说,“这儿是水…

人工智能:走向未来的智慧之路

1. 定义与范畴 人工智能&#xff08;AI&#xff09;是一门研究如何使计算机系统能够模拟人类智慧的科学与技术。这包括了机器学习、深度学习、自然语言处理、计算机视觉等多个子领域。机器学习让计算机能够通过数据学习&#xff0c;而深度学习则通过模拟人脑神经网络的方式实现…

C++数据结构:B树

目录 一. 常见的搜索结构 二. B树的概念 三. B树节点的插入和遍历 3.1 插入B树节点 3.2 B树遍历 四. B树和B*树 4.1 B树 4.2 B*树 五. B树索引原理 5.1 索引概述 5.2 MyISAM 5.3 InnoDB 六. 总结 一. 常见的搜索结构 表示1为在实际软件开发项目中&#xff0c;常用…

博途PLC SCL间接寻址编程应用

这篇博客里我们将要学习Pointer和Any指针&#xff0c;PEEK和POKE指令&#xff0c;当然我们还可以数组类型数据实现数组指针寻址&#xff0c;具体应用介绍请参考下面文章链接&#xff1a; https://rxxw-control.blog.csdn.net/article/details/134761364https://rxxw-control.b…

一文讲解如何从 Clickhouse 迁移数据至 DolphinDB

ClickHouse 是 Yandex 公司于2016年开源的 OLAP 列式数据库管理系统&#xff0c;主要用于 WEB 流量分析。凭借面向列式存储、支持数据压缩、完备的 DBMS 功能、多核心并行处理的特点&#xff0c;ClickHouse 被广泛应用于广告流量、移动分析、网站分析等领域。 DolphinDB 是一款…

【Hadoop_02】Hadoop运行模式

1、Hadoop的scp与rsync命令&#xff08;1&#xff09;本地运行模式&#xff08;2&#xff09;完全分布式搭建【1】利用102将102的文件推到103【2】利用103将102的文件拉到103【3】利用103将102的文件拉到104 &#xff08;3&#xff09;rsync命令&#xff08;4&#xff09;xsync…

使用 HTML 地标角色提高可访问性

请务必确保所有用户都可以访问您的网站&#xff0c;包括使用屏幕阅读器等辅助技术的用户。 一种方法是使用 ARIA 地标角色来帮助屏幕阅读器用户轻松浏览您的网站。使用地标角色还有其他好处&#xff0c;例如改进 HTML 的语义并更轻松地设置网站样式。在这篇博文中&#xff0c;我…

深度探索Linux操作系统 —— 构建initramfs

系列文章目录 深度探索Linux操作系统 —— 编译过程分析 深度探索Linux操作系统 —— 构建工具链 深度探索Linux操作系统 —— 构建内核 深度探索Linux操作系统 —— 构建initramfs 文章目录 系列文章目录前言一、为什么需要 initramfs二、initramfs原理探讨三、构建基本的init…

tomcat篇---第二篇

系列文章目录 文章目录 系列文章目录前言一、tomcat容器是如何创建servlet类实例?用到了什么原理?二、tomcat 如何优化?三、熟悉tomcat的哪些配置?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女…

Web应用JSON数据保护(密码算法、密钥、数字签名和数据加密)

1.JSON&#xff08;JavaScript Object Notation&#xff09; JSON是一种轻量级的数据交换格式&#xff0c;采用完全独立于编程语言的文本格式来存储和表示数据。JSON通过简单的key-value键值对来描述数据&#xff0c;可以被广泛用于网络通信、数据存储等各种应用场景&#xff0…

【重点】Flink四大基石

1. Time&#xff08;时间机制&#xff09; 时间概念 处理时间&#xff1a;执行具体操作时的机器时间&#xff08;例如 Java的 System.currentTimeMillis()) &#xff09;事件时间&#xff1a;数据本身携带的时间&#xff0c;事件产生时的时间。摄入时间&#xff1a;数据进入 …

代码随想录算法训练营第四十六天 _ 动态规划_198.打家劫舍、213.打家劫舍II、337.打家劫舍 III。

学习目标&#xff1a; 动态规划五部曲&#xff1a; ① 确定dp[i]的含义 ② 求递推公式 ③ dp数组如何初始化 ④ 确定遍历顺序 ⑤ 打印递归数组 ---- 调试 引用自代码随想录&#xff01; 60天训练营打卡计划&#xff01; 学习内容&#xff1a; 198.打家劫舍 动态规划五步曲&a…

Python面向对象基础

Python面向对象基础 一、概念1.1面向对象的设计思想1.2 面向过程和面向对象1.2.1 面向过程1.2.2 面向对象1.2.3 面向过程和面向对象的优缺点 二、类和对象2.1 概念2.2 类的定义2.3 对象的创建2.3.1 类中未定义构造函数2.3.2 类中定义构造函数 2.4 类的设计 三、类中的成员3.1 变…

vue文件下载

第一种方法 const downloadfile (url) > {if (!url) {return ElMessage.error("暂无文件&#xff01;无法下载")}axios({url,method: GET,responseType: blob// headers: {// token:getCache(TOKEN), // 可以携带token// }}).then(res > {const href …

go-zero 开发入门-API服务开发示例

接口定义 定义 API 接口文件 接口文件 add.api 的内容如下&#xff1a; syntax "v1"info (title: "API 接口文件示例"desc: "演示如何编写 API 接口文件"author: "一见"date: "2023年12月07日"version: "…

Python教程-数组

作为软件开发者&#xff0c;我们总是努力编写干净、简洁、高效的代码。在本文中&#xff0c;我们将探索 Python 数组的各种特性和功能。我们将学习如何在 Python 中创建、操作和使用数组&#xff0c;以及数组与 Python 编程语言中的其他数据结构有何不同。我们的目标是提供有关…

找重复的数据(一维数组)

在一大堆数据中找出重复的是一件经常要做的事情。现在&#xff0c;我们要处理许多整数&#xff0c;在这些整数中&#xff0c;可能存在重复的数据。 你要写一个程序来做这件事情&#xff0c;读入数据&#xff0c;检查是否有重复的数据。如果有&#xff0c;输出“YES”这三个字母…