Liunx 小程序之进度条

news2024/9/28 13:18:21

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.coloradmin.cn/o/1980724.html

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

相关文章

springboot仓库人力资源管理系统-计算机毕业设计源码45130

摘 要 仓库人力资源管理系统作为一种先进的信息技术工具&#xff0c;在企业中扮演着重要的角色。本文旨在深入探讨SpringBoot仓库人力资源管理系统的各项功能及其优势&#xff0c;以及对企业运营所带来的深远影响。 首先&#xff0c;我们详细探讨了SpringBoot仓库人力资源管理…

Opencv学习-图像变换

1. 图像连接 图像连接是指将两个具有相同高度或者宽度的图像连接在一起&#xff0c;图像的下&#xff08;左&#xff09;边缘是另一个图像的上&#xff08;右&#xff09;边缘。图像连接常在需要对两幅图像内容进行对比或者内容中存在对应信息时显示 对应关系时使用。例如&…

全国十大起名大师排行榜,中国最厉害三个起名大师是谁?

全国十大起名大师排行榜&#xff0c;中国最厉害三个起名大师是谁&#xff1f; 山东济南最受欢迎的起名大师有多位&#xff0c;其中较为知名的包括&#xff1a; ‌颜廷利&#xff0c;被誉为山东济南最出名的起名大师之一&#xff0c;还是现代山东文化名人&#xff0c;通过魔方解…

人工智能时代下,国产服务器操作系统如何加快发展?

人工智能时代下&#xff0c;国产服务器操作系统如何加快发展&#xff1f; 云智融合浪潮下&#xff0c;服务器操作系统产业未来发展将走向何方&#xff1f;英特尔和龙蜥的合作&#xff0c;能为国产操作系统的发展带来什么&#xff1f;双方如何通过合作布局“云AI”时代的未来&am…

配有知识库的AI助手与大模型问答相比,各有哪些优缺点?

1. 配有知识库支持的AI助手 优点&#xff1a; 精确性&#xff1a;知识库是由专业人员整理和维护的&#xff0c;其中的信息通常是经过验证和准确的。因此&#xff0c;配有知识库的AI助手可以提供准确的答案&#xff0c;并且在特定领域的问题上表现良好。可控性&#xff1a;知识…

合并重叠的区间

这一题不能用差分数组&#xff0c;因为 [1 , 4] [5, 6] 这个就会被合并&#xff0c;正确的做法就是先排序 bool cmp(vector<int> a, vector<int> b) {if (a[0] < b[0]) return 1;if (a[0] b[0]) return a[1] < b[1];return 0; } class Solution { public:ve…

Python酷库之旅-第三方库Pandas(065)

目录 一、用法精讲 256、pandas.Series.sparse方法 256-1、语法 256-2、参数 256-3、功能 256-4、返回值 256-5、说明 256-6、用法 256-6-1、数据准备 256-6-2、代码示例 256-6-3、结果输出 257、pandas.DataFrame.sparse方法 257-1、语法 257-2、参数 257-3、功…

分享一个基于人脸识别的小区物业管理系统Spring Boot(源码、调试、LW、开题、PPT)

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人 八年开发经验&#xff0c;擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等&#xff0c;大家有这一块的问题可以一起交流&…

我花了一天时间,搭了个专属知识库,部署上线了,手把手教,不信你学不会

自动开了这个号以后&#xff0c;陆陆续续写了很多干货文章&#xff0c;一方面是可以帮助自己梳理思路&#xff0c;另一方面也方便日后查找相关内容。 但是&#xff0c;我想检索某个关键词是在之前哪篇文章写过的&#xff0c;就有点捉急了。CSDN 还好&#xff0c;可以检索到相关…

Python 算法交易实验77 QTV200日常推进-经典策略

说明 最初(去年7月)快快上了一版&#xff0c;到现在差不多正好一年。总体上当时做的还是蛮粗糙的&#xff0c;没有考虑模式&#xff0c;只是简单的用判别模型做了一道。 过去的一年&#xff0c;显然不是特别好的一年。我知道的大部分还是以亏损居多。这版策略竟然没有亏钱&am…

【C++11】:lambda表达式function包装器

目录 前言一&#xff0c;可变参数模板1.1 简单认识1.2 STL容器中的empalce系列相关接口 二&#xff0c;lambda表达式2.1 lambda表达式语法2.2 探索lambda底层 三&#xff0c;包装器3.1 function包装器3.2 bind 四&#xff0c;类的新功能4.1 默认成员函数4.2 关键字default4.3 关…

c++数据保存到.csv文件中,并用opencv离线仿真显示

测试可能不是很方便&#xff0c;希望采集一次数据后期还可以使用&#xff0c;这里提供一个案例&#xff1a; 数据写入fosepose.csv //write.cpp #include <iostream> #include <fstream> #include <iomanip> #include <cstdint> #include <chrono…

达梦数据库的系统视图v$sql_plan

达梦数据库的系统视图v$sql_plan 达梦数据库的V$SQL_PLAN视图主要用于显示缓存中的SQL执行计划信息&#xff0c;在 ini 参数 USE_PLN_POOL !0 时才统计。通过查询这个视图&#xff0c;用户可以获取到缓存中的SQL语句的执行计划&#xff0c;这对于监控和分析数据库中的SQL执行情…

excel去掉小数点前的内容

可以使用"通配符"法 1、去除小数点后的内容 我们按CTRLH&#xff0c;调出查找替换功能 然后在查找内容里面&#xff0c;输入.* 星号是通配符&#xff0c;一点加通配符&#xff0c;表示将小数点后面的任意字符给去掉 2、去除小数点前的内容 我们按CTRLH&#xff0c;调…

Python处理和生成 Word 文档库之python-docx使用详解

概要 在日常工作中,处理和生成 Word 文档是一个常见的需求。Python 提供了一个强大的库 python-docx,使得操作 Word 文档变得简单和高效。python-docx 可以帮助我们创建、修改和读取 Word 文档,适用于各种应用场景,如自动化报告生成、批量文档处理等。本文将详细介绍 pyth…

Spring AOP:面向切面编程的最佳实践 ( 一 )

1.AOP思想 1.1.为什么需要面向切面编程 如果在一个类或者多个类的多个业务逻辑方法中, 在开始,结尾部分包含功能相同的代码称之为横切关注点也叫切面, 这种结构可能符合传统的面向对象编程&#xff08;OOP&#xff09;的封装特性, 但可能导致代码难以维护和扩展。 面向切面编…

Python 如何进行自然语言处理(NLTK, SpaCy)

自然语言处理&#xff08;Natural Language Processing, NLP&#xff09;是计算机科学和人工智能的一个重要领域&#xff0c;旨在实现计算机对人类语言的理解和处理。在Python中&#xff0c;有许多工具和库可以用于自然语言处理&#xff0c;其中最流行的两个是NLTK&#xff08;…

【Python脚本】定时任务脚本实现、自动关机等功能脚本实现(保姆篇)

文章目录 功能描述源码分析依赖参数配置数据校验多线程并发执行定时任务注册自动关机主程序 源码整合本篇小结 更多相关内容可查看 功能描述 需要python环境&#xff0c;详情可看主页python相关文章【Python】从0开始写脚本、Selenium详细教程、附源码案例&#xff08;保姆篇&…

3dsMax模型展开UV之后无法删除,3dsmax删除模型上已经展开的UV

3dsmax展开UV之后如何删除UV 方法二 如果不能重置UV通道&#xff0c;在实用工具》更多工具》UVW移除&#xff0c;选中模型&#xff0c;点击UVW移除&#xff0c;移除模型的UVW。

机器人抓取与操作的挑战与进展——挑战赛角度

从竞赛中看机器人抓取与操作的挑战与进展 前言一、国际机器人竞赛有哪些&#xff1f;二、感知方面的挑战与进展二、抓取方面的挑战与进展三、操作方面的挑战与进展总结 前言 本文根据最近的机器人抓取和操作挑战赛 (Robotic Grasping andManipulation Competitions (RGMCs))&a…