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

news2024/11/25 7:00:14

🔥博客主页:小王又困了

📚系列专栏: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.6
        cb(rate);
        //process_flush(rate);
        //printf("download: %f\n", rate); // rate出来了,应该让进度条刷新
    }
}

int main()
{
    download(process_flush);
    return 0;
}


🎁结语: 

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

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

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

相关文章

Python与ArcGIS系列(十六)重复节点检测

目录 0 简述1 实例需求2 arcpy开发脚本0 简述 在处理gis线图层和面图层数据时,有时候会遇到这种情况:数据存在重复节点或伪重复节点(两个节点距离极小),往往我们需要对这种数据进行检测标注或进行修改。本篇将介绍如何利用arcpy及arcgis的工具箱实现这个功能。 1 实例需求…

【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…

PR剪辑视频做自媒体添加字幕快速方式(简单好用的pr视频字幕模板)

如何选择合适的字幕添加进短视频呢&#xff1f;首先要先确定增加的视频风格&#xff0c;简约、商务、科技感、炫酷&#xff1b;再确定用途&#xff0c;注释、标记、语音翻译、引用、介绍&#xff1b;最后在相应的模板中挑选几个尝试&#xff0c;悬着一个最切合主题的使用&#…

【C++学习手札】基于红黑树封装模拟实现map和set

​ &#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 &#x1f49c;本文前置知识&#xff1a; 红黑树 ♈️今日夜电波&#xff1a;漂流—菅原纱由理 2:55━━━━━━️&#x1f49f;──────── 4:29 …

node js 递归生成vue文件目录

目录 什么是 fs 文件系统模块 fs.existsSync方法 方法说明&#xff1a; 语法&#xff1a; 向指定的文件中写入内容 writeFile fs.writeFile() 的语法格式 fs.writeFile() 的示例代码 判断文件是否写入成功 fs.mkdir 创建目录 目录已存在&#xff0c;重复创建 创建的目…

Linux各目录结构说明

文章目录 目录说明源码放哪里&#xff1f;拓展&#xff1a;Linux里面安装软件是装在home目录还是opt目录还是/usr/local好&#xff1f; bin boot dev etc home lib lib64 lostfound media mnt opt proc root run sbin srv sys tmp usr var 目录说明 bin 存放二进制可执行文件&…

玩转大数据11:数据可视化与交互式分析

1. 引言 数据可视化和交互式分析是大数据领域中的重要方面。随着大数据时代的到来&#xff0c;数据量越来越大&#xff0c;数据类型越来越复杂&#xff0c;传统的数据处理和分析方法已经无法满足我们的需求。数据可视化可以将复杂的数据以简单、直观的方式呈现出来&#xff0c…

素材创作平台,解决企业素材供给问题

企业对于高质量素材的需求日益增长。无论是为了提升品牌形象&#xff0c;还是为了推动产品销售&#xff0c;都需要大量的专业设计素材。然而&#xff0c;素材的获取、设计和定制往往是一项耗时耗力的工作。这时&#xff0c;美摄科技素材创作平台应运而生&#xff0c;为企业提供…

JVM 虚拟机 类的加载器分类与测试详解

Java全能学习面试指南&#xff1a;https://javaxiaobear.cn 1、类加载器的分类说明 JVM支持两种类型的类加载器&#xff0c;分别为引导类加载器&#xff08;Bootstrap ClassLoader&#xff09;和自定义类加载器&#xff08;User-Defined ClassLoader&#xff09;。 从概念上来…

webpack该如何打包

1.我们先创建一个空的大文件夹 2.打开该文件夹的终端 输入npm init -y 2.1.打开该文件夹的终端 2.2在该终端运行 npm init -y 3.安装webpack 3.1打开webpack网址 点击“中文文档” 3.2点击“指南”在点击“起步” 3.3复制基本安装图片画线的代码 4.在一开始的文件夹下在创建一…

营收增速持续放缓,博通CEO期待AI崛起救场 | 百能云芯

博通作为苹果等大型科技公司的芯片供应商&#xff0c;于周四发布了财报。尽管截至10月29日的第四季度营收增长了4%至93亿美元&#xff0c;符合市场预期&#xff0c;但增速已经降至2020年以来的最低水平。 由于企业客户和电信供应商在控制支出方面的谨慎态度&#xff0c;博通的销…

C 语言 变量

变量初始值 全局变量&#xff1a;初始值是 0 局部变量&#xff1a;初始值是 随机的 类型限定符 通常不需要显式使用 register 关键字来优化变量的存储和访问。 关键字 _Complex和_Imaginary分别用于表示复数和虚数&#xff08;二者皆是数学概念&#xff09; 变量的声明和定义 c…

【小白专用】MySQL创建数据库和创建数据表

1.在Windows开始搜索输入Mysql,并选择第一个打开。 2.输入安装时的密码 3.说明安装成功。 二、创建数据库 1. 连接 MySQL 输入 mysql -u root -p 命令&#xff0c;回车&#xff0c;然后输入 MySQL 的密码(不要忘记了密码)&#xff0c;再回车&#xff0c;就连接上 MySQL 了。 …

Vue3选项式-基础部分篇

Vue3选项式风格-基础部分篇 简介模板语法文本插值原始HTMLAttribute 绑定使用 JavaScript 表达式调用函数全局组件调用内置指令动态参数注意事项 data()data()深度响应 methods有状态的methods(防抖) DOM更新时机计算属性class和style绑定条件渲染列表渲染数组变换侦听事件处理…

全网最新最全【Kali Linux】 渗透测试技术大全

利矛出击&#xff1a;Kali Linux 渗透测试大法 在网络攻防实践中&#xff0c;系统的防御措施可以称为“盾”&#xff0c;而渗透测试则是“矛”。二者同等重要&#xff0c;因为“矛”可以试探出“盾”有多坚固&#xff0c;并且及时发现问题&#xff0c;修补漏洞&#xff0c;提升…

k8s之镜像拉取时使用secret

k8s之secret使用 一、说明二、secret使用2.1 secret类型2.2 创建secret2.3 配置secret 一、说明 从公司搭建的网站镜像仓库&#xff0c;使用k8s部署服务时拉取镜像失败&#xff0c;显示未授权&#xff1a; 需要在拉取镜像时添加认证信息. 关于secret信息,参考: https://www.…

[英语学习][10][Word Power Made Easy]的精读与翻译优化

[序言] 下面这段话, 译者翻译没有太大问题, 就是某些单词上, 跟他理解得不一样. 另外还有一个关键的定语从句, 我认为译者理解不到位, 导致翻译不够通顺. [英文学习的目标] 提升自身的英语水平, 对日后编程技能的提升有很大帮助. 希望大家这次能学到东西, 同时加入我的社区讨…

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

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

matlab RGB三元组和十六进制的转换

matlab画柱状图改颜色的时候&#xff0c;用三元组的形式&#xff0c;范围是[0&#xff0c;1] 我们获得了十六进制 到网站转换为[0,255] https://c.runoob.com/front-end/55/ 然后将得到的值/255 输入matlab就可以了

VS2009和VS2022的错误列表可复制粘贴为表格

在VS2019或VS2022中&#xff0c;可看到如下错误列表&#xff1a; 如果复制这两行错误信息&#xff1a; 然后把它粘贴到word文件&#xff0c;就可以看到以下表格&#xff1a; 严重性 代码 说明 项目 文件 行 禁止显示状态 错误(活动) E0020 未定义标识符 "dd"…