【Linux】编写第一个小程序:进度条

文章目录

  • 1. 预备知识
    • 1.1 简单认识几个函数
      • 1.1.1 sleep()
      • 1.1.2 fflush()
      • 1.1.3 usleep()
      • 1.1.4 memset()
    • 1.2 缓冲区
    • 1.3 回车与换行
  • 2. 编写入门版的进度条
    • 2.1 基本逻辑
    • 2.2 美化效果
    • 2.3 代码实现
    • 2.4 执行效果
  • 3. 编写升级版的进度条
    • 3.1 代码实现
    • 3.2 执行效果

在这里插入图片描述

1. 预备知识

1.1 简单认识几个函数

1.1.1 sleep()

unsigned int sleep(unsigned seconds);
  • 作用:让程序休眠指定秒数,如:sleep(3); //让程序休眠3秒
  • 与 Windows 上的 Sleep() 函数不同
  • 需要包含头文件<unistd.h>

1.1.2 fflush()

int fflush(FILE* stream);
  • 作用:刷新缓冲区
  • 需要传入一个流
  • 需要包含头文件<stdio.h>

1.1.3 usleep()

int usleep(useconds_t usec);
  • 作用:让程序休眠指定微秒,如:usleep(100000); //让程序休眠100000微秒(0.1秒)
  • 1秒 = 1000000微秒
  • 需要包含头文件<unistd.h>

1.1.4 memset()

void* memset(void* ptr, int value, size_t num);
  • 作用:将 ptr 指向的内存块的前 num 个字节设置为指定的 value 值
  • 返回设置后的 ptr
  • 需要包含头文件<string.h>

1.2 缓冲区

直接上代码观察现象

#include <stdio.h>
#include <unistd.h>int main()
{printf("you can see me       ");sleep(3);return 0;
}

执行效果图

在这里插入图片描述

  • 首先要否定上面不切实际的想法,C语言是顺序执行的,所以 printf 函数一定先于 sleep 函数执行。
  • 那为什么 3 秒后才打印到屏幕上呢?当然是因为缓冲区!
  • printf 函数跑完后,输出的字符串是被保存到 C 对 IO 函数提供的一个缓冲区里了,在程序退出的时候,缓冲区中的内容才被刷新到屏幕上
  • 我们需要使用上面讲的 fflush 函数把缓冲区中的内容提前强制刷新到屏幕上,使用方法:fflush(stdout);

1.3 回车与换行

首先我要抛出一个概念:回车和换行是不一样的!

  • 回车( \r ):把光标放到当前行的开始。

在这里插入图片描述

  • 换行( \n ):把光标放到当前位置的下一行。

在这里插入图片描述

  • 所以理论上来讲,‘\n’ 和 ‘\r’ 一起用才是我们理解中的”回车“,即:把光标放到下一行最开始的位置。

2. 编写入门版的进度条

2.1 基本逻辑

  • 进度 1% 打印 1 个字符,回车到开始的位置,刷新缓冲区;
  • 进度 2% 打印 2 个字符,回车到开始的位置,刷新缓冲区;
  • 进度 100% 打印 100 个字符,回车到开始的位置,刷新缓冲区,程序终止。

在这里插入图片描述

2.2 美化效果

  • 进度条主体增加箭头显示
  • 显示进度百分比
  • 添加一个动态的旋转光标

在这里插入图片描述

2.3 代码实现

// porcessbar.h#pragma once#include <stdio.h>#define NUM 103
#define Body '='
#define Head '>'// version 1
void process();
// processbar.c#include "processbar.h"
#include <string.h>
#include <unistd.h>const char* lable = "|/-\\";// version 1
void process()
{char buffer[NUM];memset(buffer, '\0', sizeof(buffer));int cnt = 0;int n = strlen(lable);buffer[0] = Head;while (cnt <= 100){printf("[%-100s][%3d%%][%c]\r", buffer, cnt, lable[cnt % n]);fflush(stdout);buffer[cnt++] = Body;if (cnt < 100){buffer[cnt] = Head;}usleep(50000);}printf("\n");
}

2.4 执行效果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3. 编写升级版的进度条

  • 上面的进度条算是一个进度条吗?我们的进度条似乎在一个人玩单机呀,这样的进度条是没有意义的。
  • 进度条的进度应该是依赖于其他应用的,比如下载。
  • 下面我们模拟一个下载环境,并修改进度条,使进度条可以根据下载的进度,同步进行显示进度的工作。

3.1 代码实现

// processbar.h#pragma once#include <stdio.h>#define NUM 103
#define Body '='
#define Head '>'typedef void (*callback_t)(double);		// 函数指针类型// version 2
void process_flush(double rate);
// processbar.c#include "processbar.h"
#include <string.h>
#include <unistd.h>const char* lable = "|/-\\";// version 2: 进度是多少,你进度条能知道吗?另外,什么进度?依附于其他应用的,比如下载
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("[%-100s][%.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#include "processbar.h"
#include <time.h>
#include <stdlib.h>
#include <unistd.h>// 模拟文件大小
#define FILESIZE (1024 * 1024 * 1024)// 模拟一种场景,表示一种下载任务
void download(callback_t cb)    // 回调函数的形式
{srand(time(NULL) ^ 1023);   // 这样写只是为了让随机数更随机int total = FILESIZE;while (total){usleep(10000);  // 下载动作int one = rand() % (1024 * 1024);  // 一次下载的大小total -= one;if (total < 0){total = 0;}// 当前的进度是多少?int download = FILESIZE - total;double rate = (download * 1.0 / FILESIZE) * 100.0;cb(rate);}
}int main()
{download(process_flush);return 0;
}

3.2 执行效果

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


END

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

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

相关文章

Defi安全--Zunami Protocol攻击事件分析

其它相关内容可见个人主页 1 Zunami攻击事件相关信息 2023.8.13发生在Ethereum上发生的攻击&#xff0c;存在两个攻击交易&#xff0c;具体信息如下&#xff1a; 攻击合约地址&#xff1a;Contract Address 攻击合约 攻击者地址&#xff1a;Zunami Protocol Exploiter 攻击…

机器学习_实战框架

文章目录 介绍机器学习的实战框架1.定义问题2.收集数据和预处理(1).收集数据(2).数据可视化(3).数据清洗(4).特征工程(5).构建特征集和标签集(6).拆分训练集、验证集和测试集。 3.选择算法并建立模型4.训练模型5.模型的评估和优化 介绍机器学习的实战框架 一个机器学习项目从开…

【Python进阶必备】一文掌握re库:实战正则表达式

目录 re库初识 re库基础使用方法 compile()函数 基本用法 正则表达式常用规则字符 match与search方法 match search match/search findall与finditer方法 使用findall()返回所有匹配项 使用findall()提取多个组的匹配 使用finditer()逐个返回Match对象 使用findi…

如何在 SwiftUI 中实现音频图表

文章目录 前言DataPoint 结构体BarChartView 结构体ContentView 结构体实现协议实现线图总结 前言 在可访问性方面&#xff0c;图表是复杂的事物之一。iOS 15 引入了一项名为“音频图表”的新功能。 下面我们将学习如何通过使用 accessibilityChartDescriptor 视图修饰符为任…

必须掌握的100+个Linux命令大全【持续更新中】

别有一番风趣的alias … note:: 寒蝉凄切&#xff0c;对长亭晚&#xff0c;骤雨初歇。 柳永《雨霖铃》 Linux alias命令用于设置指令的别名&#xff0c;可以将比较长的命令进行简化。 默认情况下会输出当前的设置&#xff1a; $ alias lls -lah lals -lAh llls -lh lsls --…

C语言操作符详解与进制

目录 一&#xff1a;操作符的分类 二&#xff1a;二进制和进制转换 2.1 2进制转10进制 2.1.1 10进制转2进制数字 2.2 2进制转8进制和16进制 2.2.1 2进制转8进制 2.2.2 2进制转16进制 三&#xff1a; 原码、反码、补码 四&#xff1a;移位操作符 4.1左移操作符 4.2 右…

<蓝桥杯软件赛>零基础备赛20周--第14周--BFS

报名明年4月蓝桥杯软件赛的同学们&#xff0c;如果你是大一零基础&#xff0c;目前懵懂中&#xff0c;不知该怎么办&#xff0c;可以看看本博客系列&#xff1a;备赛20周合集 20周的完整安排请点击&#xff1a;20周计划 每周发1个博客&#xff0c;共20周。 在QQ群上交流答疑&am…

Excel地址

解题思路&#xff1a; 根据题中歪歪和笨笨的话可以有两种解法。 1.输入的数为多大&#xff0c;则循环1多少次&#xff0c;当值为27时就要进行进位操作。这时要分情况讨论。 当集合中元素为一个时&#xff0c;如26&#xff0c;则需要变为1 1&#xff0c;集合元素个数加一。 当…

nova组件讲解和glance对接swift

1、openstack架构 &#xff08;1&#xff09;openstack是一种SOA架构&#xff08;微服务就是从这种架构中剥离出来的&#xff09; &#xff08;2&#xff09;这种SOA架构&#xff0c;就是把每个服务独立成一个组件&#xff0c;每个组件通过定义好的api接口进行互通 &#xff…

服务异步通讯——springcloud

服务异步通讯——springcloud 文章目录 服务异步通讯——springcloud初始MQRabbitMQ快速入门单机部署1.1.下载镜像安装MQ SpringAMQPwork Queue 工作队列Fanout Exchange广播模式DirectExchange路由模式TopicExchange话题模式 消息转换器 初始MQ RabbitMQ快速入门 官网https:/…

将Python程序打包成exe文件

一、什么是exe可执行文件&#xff1f; **exe文件英文全名是executable file&#xff0c;翻译为可执行文件&#xff08;但它不等于可执行文件&#xff09;&#xff0c;可执行文件包含两种&#xff0c;文件扩展名为.exe的是其中的一种。exe文件可以在Windows平台上直接双击运行&a…

17. 电话号码的字母组合(回溯)

从第一个数字开始遍历其对应的字母&#xff0c;将其加入StringBuffer中&#xff0c;继续深度优先搜索&#xff0c;当访问到最后一个数字的时候&#xff0c;将StringBuffer存储到ans中&#xff0c;然后回溯到下一个对应字母。 class Solution {public List<String> lette…