Liunx 小程序之进度条

Liunx 小程序之进度条

  • 效果
  • 前提条件
    • 回车和换行
    • 缓冲区
      • 倒计时
  • 进度条
    • 纯进度条
    • 模拟下载的进度条
      • Progressbar.h
      • Progressbar.c
      • main.c
      • makefile

效果

先来看效果,这其实是一个动态的进度条,后有源码,运行即可:

在这里插入图片描述

在这里插入图片描述

前提条件

在制作之前有两个前提条件需要了解

回车和换行

这个概念,一般人均会混为一谈,而程序员因为熟知 '\n' ,所以深刻理解 换行符将当前光标位置换到下一行的开头

'\n' 这个字符其实是两个动作,一个是 回车 ,一个是 换行

  • 换行:顾名思义,只是将当前光标位置换进下一行,但是其在下一行的什么位置,取决于之前上一行的所在位置
  • 回车:这是 将光标置于此行开头位置

所以一般来说, 换行符 所完成的是这 两个动作 的总和

而在 C 语言里,只 回车'\r' ,所以有些人会写出 "\r\n" 这样的代码,这时候的 '\n' 就只表示 换行

缓冲区

有了上面 回车换行 的解释,对于 缓冲区 ,我们需要对比观察这样两份代码:

// 第一份代码:
#include <stdio.h>
#include <unidstd.h>
int main()
{printf("Hello World...\n");sleep(3);return 0;
}
// 第二份代码:
#include <stdio.h>
#include <unidstd.h>
int main()
{printf("Hello World...");sleep(3);return 0;
}

不同之处 仅在于代码 printf("Hello World..."); 打印的字符串是否含有 '\n' 换行符

那么请将这两份代码放在命令行终端进行验证,分别编译运行后,眼睛看到的结果将不一样

  1. 第一份会将 Hello World... 打印出来并空出一行,休眠 3 秒
  2. 第二份会先休眠 3 秒,再打印出 Hello World... 这时由于没有 换行符,下一个 命令行提示符 会紧跟字符串打印出来

请注意,这是肉眼观察到的结果,那为什么第二份代码肉眼观察是先休眠呢?

首先我们知道,C 语言对上面的两份代码一定是 顺序执行 的,也就是说 均为先打印,后休眠 ,既如此,那第二份代码的字符串为何等休眠后才出现呢?真正的字符串又被打印在了哪里?

首先,缓冲区可以看作是内存里的一块空间; printf 函数也并不是把字符串直接显示在显示器屏幕上,而是将字符串拷贝进这块缓冲区,再由缓冲区刷新到显示器屏幕上

第二段程序由于没有 '\n',会将字符串一直放在缓冲区里,直到程序结束,自动冲涮缓冲区时才被刷新到屏幕上

目前来说 缓冲区的刷新策略是:

  1. 含有 '\n' ,会将 '\n' 前面所有的内容都刷新出来(行刷新)
  2. 缓冲区满即刷新
  3. 使用函数 fflush(stdout); 强制刷新

倒计时

有了上面的解释,咱就可以先着手写一个 倒计时 ,代码如下:

// pre-test.c 源文件
#include <stdio.h>
#include <unistd.h>
int main()
{for (int i = 10; i >= 0; --i){printf("倒计时:%2d\r", i);fflush(stdout);sleep(1);}printf("\n");return 0;
}
# makefile 文件
bin=pre-test
src=pre-test.c$(bin):$(src)gcc $^ -o $@ -std=c99.PHONY:clean
clean:rm -f $(bin)

试一试咯 ^ ^

进度条

纯进度条

我们先完成一个 纯进度条 的代码:

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

如果能看懂前面 倒计时 的代码,那这里的代码也就可以看懂了,原理都一样,如果运行你会发现,这是个自主加载的进度条,不表示任何事物的进度,那怎么行,接下来我们模拟 下载的进度条

模拟下载的进度条

只要将 纯进度条 看懂,那接下来的代码也一定可以看懂,其实原理和 倒计时 一样,代码不做解释

下面我将把代码写成结构化形式,利用 make 自动化构建

Progressbar.h

#pragma once #include <stdio.h> 
#include <unistd.h> // 定义函数指针,用于回调函数
typedef void(* callback_t)(double, double);void ProsBar(double total, double current);

Progressbar.c

#include "Progressbar.h" 
#include <string.h> #define Length 101
#define Style '#'const char* lable = "|/-\\";void ProsBar(double total, double current)
{static char bar[Length] = { 0 };// memset(bar, '\0', sizeof(bar));static int cnt = 0;int len = strlen(lable);double rate = (current * 100.00) / total;int loop_count = (int)rate;while (cnt <= loop_count){bar[cnt++] = Style;// usleep(10000);}printf("[%-100s][%.2lf%%][%c]\r", bar + 1, rate, lable[(cnt - 1) % len]);fflush(stdout);if (cnt >= 100){cnt = 0;memset(bar, '\0', sizeof(bar));}
}

main.c

#include "Progressbar.h" void Download_Simulation(callback_t cb)
{double FileSize = 100 * 1.0;  // 文件大小double Current = 0.0;         // 下载进度double BandWidth = 1.0;       // 网络带宽printf("Download start!\n");while (Current <= FileSize){cb(FileSize, Current);Current += BandWidth;usleep(50000);}printf("\nThe file size is %.2lf MB\nDownload complete!\n", FileSize);
}int main()
{// 回调函数Download_Simulation(ProsBar);return 0;
}

makefile

bin=Progressbar 
src=main.c Progressbar.c$(bin):$(src)gcc $^ -o $@.PHONY:clean
clean:rm -f $(bin)

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

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

相关文章

数论基础知识(上)

目录 数学符号 整除与约数 最大公约数&#xff08;gcd)和最小公倍数&#xff08;lcm) 质数 (素数) 算术基本定理&#xff08;唯一分解定理&#xff09; 约数个数 约数之和 分解质因数&#xff08;枚举法&#xff09; 试除法求约数&#xff08;枚举法&#xff09; 数学…

RTSP系列四:RTSP Server/Client实战项目

RTSP系列&#xff1a; RTSP系列一&#xff1a;RTSP协议介绍-CSDN博客 RTSP系列二&#xff1a;RTSP协议鉴权-CSDN博客 RTSP系列三&#xff1a;RTP协议介绍-CSDN博客 RTSP系列四&#xff1a;RTSP Server/Client实战项目-CSDN博客 目录 一、RTSP Server实战项目 1、准备 2、…

F4Pan网盘解析获取下载链接的工具系统源码

F4Pan网盘解析获取下载链接的工具系统源码&#xff0c;F4Pan(下称本项目)使用的接口全部来自于官方&#xff0c;无任何破坏接口的行为&#xff0c;本项目所有代码全部开源&#xff0c;仅供学习参考使用&#xff0c;请遵守相关的法律法规&#xff0c;禁止商用&#xff0c;若无视…

java+springboot+mysql校园二手书销售平台设计与实现00895-计算机毕业设计项目选题推荐(附源码)

摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对校园二手书销售平台等问题&#xff0c;对校…

快速体验LLaMA-Factory 私有化部署和高效微调Llama3模型FAQ

序言 之前已经介绍了在超算互联网平台SCNet上使用异构加速卡AI 显存64GB PCIE&#xff0c;私有化部署Llama3模型&#xff0c;并对 Llama3-8B-Instruct 模型进行 LoRA 微调、推理和合并 &#xff0c;详细内容请参考另一篇博客&#xff1a;快速体验LLaMA-Factory 私有化部署和高…

计算机网络基础 - 计算机网络和因特网(2)

计算机网络基础 计算机网络和因特网Internet 结构和 ISP分组延时、丢失和吞吐量四种分组延时分组丢失吞吐量 协议层次及其服务模型概念数据单元&#xff08;DU&#xff09;协议栈TCP/IP 协议各层次的协议数据单元IOS/OSI 参考模型 计算机网络和因特网的历史早期计算机网路&…

自动驾驶的六个级别是什么?

自动驾驶汽车和先进的驾驶辅助系统&#xff08;ADAS&#xff09;预计将帮助拯救全球数百万人的生命&#xff0c;消除拥堵&#xff0c;减少排放&#xff0c;并使我们能够在人而不是汽车周围重建城市。 自动驾驶的世界并不只由一个维度组成。从没有任何自动化到完整的自主体验&a…

偷懒神器:auto 的讲解

1. auto 的定义 在c/c11之前&#xff0c;auto用来修饰局部变量&#xff0c;表明该变量是一个自动变量&#xff0c;函数结束后该变量销毁   c11中&#xff0c;赋予auto全新的含义。其中表示&#xff1a;auto不再是一个存储类型指示符&#xff0c;而是作为一个新的类型指示符来…

熊海1.0cmsPHP代码审计

熊海1.0cmsPHP代码审计 环境搭建 下载之后直接使用phpstduy搭建就好了 工具使用 比如使用seay审计系统 sql大多数是存在的&#xff0c;但是没有文件上传&#xff0c;这个就是需要自己去验证 漏洞审计 SQL注入 有点多&#xff0c;随便拿一个举例子 就比如我们的登录页面…

Ceres Cuda加速

文章目录 一、简介二、准备工作三、实现代码四、实现效果参考资料一、简介 字Ceres2.2.1版本之后,作者针对于稠密矩阵的分解计算等操作进行了Cuda加速,因此这里就基于此项改动测试一下效果。 二、准备工作 1、首先是需要安装Cuda这个英伟达第三方库,https://developer.nvidi…

日企的“目标式招聘”到底什么意思?

看到篇文章称&#xff1a;日企的目标式招聘&#xff0c;高效率招聘。这是什么意思呢&#xff1f;小编今天来跟大家讲一讲。 首先&#xff0c;日企的目标式招聘&#xff0c;其实企业也是迫不得已。一个大型企业的招聘负责人说&#xff1a;“以前我们都是认真地考察每一位应聘者&…

Vue 使用elementUI-plus el-calendar加 公历转农历 是否节假日 等

效果图&#xff1a; 1. 使用到自定文件 calendar.js /*** 1900-2100区间内的公历、农历互转* charset UTF-8* Author Jea杨(JJonlineJJonline.Cn)* Time 2014-7-21* Time 2016-8-13 Fixed 2033hex、Attribution Annals* Time 2016-9-25 Fixed lunar LeapMonth Param…

浏览器事件循环详解

1. 浏览器的进程模型 1.1. 何为进程&#xff1f; 程序运行需要有它自己的专属内存空间&#xff0c;可以把这块内存空间简单的理解为进程。 每个应用至少有一个进程&#xff0c;进程之间相互独立&#xff0c;即使要通信&#xff0c;也需要双方同意。 1.2. 何为线程&#xff1f…

NodeJS的安装【windows】

文章目录 1 安装包下载2 下载过程3 测试 1 安装包下载 Node.js中文网&#xff1a;https://nodejs.cn 2 下载过程 3 测试

【游戏引擎之路】登神长阶(八)——Python之旅行,休息一下,去看看新世界

5月20日-6月4日&#xff1a;攻克2D物理引擎。 6月4日-6月13日&#xff1a;攻克《3D数学基础》。 6月13日-6月20日&#xff1a;攻克《3D图形教程》。 6月21日-6月22日&#xff1a;攻克《Raycasting游戏教程》。 6月23日-7月1日&#xff1a;攻克《Windows游戏编程大师技巧》。 7月…

基于huggingface和langchain快速开发大模型应用

目录 一、HuggingFace. 2 1.1定义... 2 1.2活跃度... 2 1.3 工具集... 2 二、HuggingFace工具介绍... 3 2.1 Pipelines. 3 2.1.1定义... 3 2.1.2常见参数... 3 2.2、AutoClass. 4 2.2.1定义... 4 2.2.2 支持模型架构列表... 4 三、HuggingFace案例介绍... 4 3.1基…

Midjourney小技巧-提升出图质量的常用公式

一个公式让你的Midjourney生成更具韵味的人像身影图 step1-测试&#xff1a;输入提示词 - 一个面容精致的亚洲女性 - An Asian woman with a delicate face 生成的图片还是挺唯美的&#xff0c;就是过于单调&#xff0c;稀疏平常 step2-使用公式&#xff1a; 谁谁&#xff0…

flutter开发环境搭建与android studio 安装配置

flutter开发环境搭建与android studio 安装配置 安装 android studio 下载安装 Android Studio 开发工具 Android Studio官网安装的时看到配置路径就换成自己其他盘的路径即可&#xff0c;其他的一路下一步就ok安装完毕&#xff0c;运行打开缺少 android sdk 按照提示下载即可…

C++ 继承 派生类的运算符重载

C(二十二)派生类的运算符重载 语法赋值顺序引例1:当子类,不自实现赋值运算符函数重载时,默认调用父类的赋值运算符函数引例2:子类自实现赋值运算符函数重载,不做特殊处理时,只会调用父类的赋值运算符函数.引例3:子类自实现赋值运算符函数重载,在函数体内调用父类的赋值运算符函…

【leetcode】平衡二叉树、对称二叉树、二叉树的层序遍历(广度优先遍历)(详解)

Hi~&#xff01;这里是奋斗的明志&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f331;&#x1f331;个人主页&#xff1a;奋斗的明志 &#x1f331;&#x1f331;所属专栏&#xff1a;数据结构、LeetCode专栏 &#x1f4da;本系…