【linux】倒计时小程序、进度条小程序及其puls版本

news2025/5/13 12:04:36

小编个人主页详情<—请点击
小编个人gitee代码仓库<—请点击
linux系列专栏<—请点击
倘若命中无此运,孤身亦可登昆仑,送给屏幕面前的读者朋友们和小编自己!
在这里插入图片描述


目录

    • 前言
    • 一、知识铺垫
      • 1. 回车换行
      • 2. 缓冲区
    • 二、倒计时小程序
      • 1. 实现
    • 三、进度条小程序
      • 1. 基本框架
      • 2. 实现细节
        • 1. makefile
        • 2. progressBar.h
        • 3. main.c
        • 4. progressBar.c
    • 四、进度条小程序plus升级版本
        • 1. makefile
        • 2. progressBar.h
        • 3. main.c
        • 4. progressBar.c
    • 总结


前言

【linux】linux项目自动化构建工具-make/Makefile—书接上文详情请点击<—
本文由小编为大家讲解—倒计时小程序、进度条小程序


一、知识铺垫

1. 回车换行

我们键盘上的enter键其实作用是回车并换行,回车是指让当前的光标移动至当前行的起始位置,换行是换到下一行径直向下的对应的那一个位置
在这里插入图片描述

  1. 在linux中我们使用 ‘\r’ 表示回车,使用 ‘\n’ 表示回车换行

2. 缓冲区

  1. 我们在文件中编写一个这样的代码,sleep函数的作用是休眠指定n秒,在这里对应休眠2秒,sleep的头文件是#include <unistd.h>
    在这里插入图片描述

  2. 使用gcc进行编译链接为可执行程序之后,运行,我们知道c语言程序的执行是从上往下开始进行执行的,那么小编调用printf打印在屏幕上的hello去哪了呢,为什么既然是从上往下逐语句执行为什么不显示hello呢?

在这里插入图片描述

  1. 2秒后,我们的hello被打印在了屏幕上,这究竟是为什么呢?首先我们的hello最开始没有打印出来,2秒后被打印出来了,那么说明这个hello字符串一定没有丢失,一定被保存起来了,这个保存的位置就叫做缓冲区,这个缓冲区是由c语言维护的一段内存,当程序结束或遇到’\n’的时候会进行刷新缓冲区的内容,这时候当执行完sleep休眠2秒后程序结束,缓冲区的内容自然也就被刷新出来显示在屏幕上

在这里插入图片描述

  1. 那么我们有没有办法可以强制刷新缓存区的内容呢?有的,可以使用fflush函数强制刷新缓冲区的内容,fflush函数需要传参对应的流,流分为标准输入流(stdin),标准输出流(stdout),标准错误流
  2. 由于是将hello刷新输出到我们的屏幕上,所以需要传入标准输出流(stdout)即 stdout 作为fflush的参数

在这里插入图片描述

  1. 那么我们对应修改一下我们的代码,调用fflush强制刷新缓冲区即可
    在这里插入图片描述
  2. 使用gcc进行编译链接为可执行程序之后,运行之后由于c语言程序是逐语句进行执行,hello被存储在了缓冲区,接着fflush函数会立即刷新缓冲区,那么缓冲区的内容hello就被刷新出来并立即显示到了屏幕上
    在这里插入图片描述
  3. 由于输出hello之后,还有sleep需要休眠2秒,所以2秒之后程序结束
    在这里插入图片描述

二、倒计时小程序

先看效果
在这里插入图片描述

1. 实现

  1. 我们默认生成10秒的倒计时,这个可以自行修改,取决于自己
  2. sleep的头文件是#include <unistd.h>
  3. 那么实现原理很简单,使用一个while循环即可,那么需要注意使用fflush刷新缓冲区,并且使用sleep每次打印后休眠1秒,这样才有一个倒计时的效果
  4. 同时10其实在电脑上的打印是字符’1’和字符’0’,如果不加格式控制我们使用回车打印9之后在屏幕上显示就变成了字符’9’和字符’0’,所以我们需要进行格式控制,这里的格式控制使用%2d,即默认占两个字符(10就是两个字符),如果实际内容为1个字符(从0到9都是1个字符),那么另一个字符位置不显示内容,这样生成之后,由于默认是右对齐,所以在屏幕上打印字符’9’,就变成了空格字符’9’,不符合我们的阅读习惯,所以我们修改一下默认对齐方式修改成左对齐即%-2d即可
  5. 最后为了我们的0在经过回车之后,在程序结束之后,bash命令行要进行显示,那么就会把我们的0给覆盖,为了0不被覆盖,我们人为加一个换行即可
#include <stdio.h>
#include <unistd.h>

int main()
{
	int cnt=10;
	
	while(cnt>=0)
	{
		printf("%-2d\r",cnt);
		fflush(stdout);
		
		cnt--;
		
		sleep(1);
	}
	
	printf("\n");
	
	return 0;
 }  

三、进度条小程序

先看效果
在这里插入图片描述

1. 基本框架

进度条的英文是progressbar,这里给文件起名要对应,我们建立两个源文件progressBar.c文件用于编写进度条函数的实现,main.c文件用于编写进度条函数和基本框架逻辑,一个头文件用于编写头文件和函数声明和宏定义
同时为了便于使用make/makefile的自动化构建,我们还要创建一个makefile文件用于配置编译和清理工作
在这里插入图片描述

2. 实现细节

1. makefile

【linux】linux项目自动化构建工具-make/Makefile—学习make/makefile详情请点击<—,根据此文章,小编对于makefile的配置只讲解重点

  1. 关于makefile配置如下,我们编译main.c和progressBar.c并链接即可,这里我们没有加入头文件,因为头文件已经包含在了源文件中,进行预处理的时候会在源文件进行展开
progressBar:main.c progressBar.c
	gcc $^ -o $@

.PHONE:clean
clean:
	rm -f progressBar
2. progressBar.h
  1. #pragma once是条件编译,防止头文件被重复展开
  2. 要使用到memset函数其对应的头文件是#include <string.h>,要使用到usleep函数其对应的头文件是#include <unistd.h>,这里的usleep的单位是微秒,我们可以更为精细的控制程序执行完成的总时间,1秒等于1000毫秒,1毫秒等于1000微秒,所以1秒等于1000000微秒,我们在调用进度条函数的时候要传入每次打印的时间,一般是设置为50000微秒,程序总执行100次,那么就是5000000微秒,即程序被我们设定为了5秒跑完
  3. 进度条的头’>‘和身体’-'这里我们将其设置为宏,便于修改
  4. 函数声明前也可不加extern,但是全局变量的声明必须加extren
#pragma once                                                                                                                                             

#include <stdio.h>
#include <unistd.h>
#include <string.h>

#define BODY '-'
#define RIGHT '>'

extern void progressbar(int speed);
3. main.c
  1. main.c文件中包含着调用进度条函数,是整个程序的基本框架的主逻辑,这里的调用参数为什么设置为50000的原因在progressBar.h中有讲,具体原因请看上文
#include "progressBar.h"

int main()
{
	progressbar(50000);                                                                                                                                    

	return 0;
}
4. progressBar.c

在这里插入图片描述

  1. 我们要实现的是一个带有进度条并且带有百分之多少的进度并且带有一个类似于加载旋转的三个功能的程序,我们使用[ ]进行分隔这三个功能
  2. 进度条我们可以使用字符数组来进行模拟,从0个字符到100个字符,并且打印我们使用printf打印字符串%s的打印方式,遇到’\0’打印字符串才会停止,由于我们要展示100个字符,在第100个字符的后面我们还应该放一个’\0’,用于终止字符串的打印,所以我们的数组中要先开101个空间并且使用memset函数全部初始化为’\0’,但是实际上要开102个空间,具体原理请继续往下阅读
  3. 我们的过程由于是要向屏幕上打印100个’-'用于表示进度加载完成,最开始为0个,那么就有101次循环,我们定义一个变量为0,当它小于等于100的时候执行代码逻辑,那么这样就可以实现出有101次循环,那么接下来小编带你们模拟一下过程,并且证明字符数组要开102个空间,程序才能够正常运行

在这里插入图片描述

  1. 我们的模拟加载旋转的字符这里就采用|/-\进行模拟,其中\是特殊的转义字符,我们要使用双\\才能进行显示,所以这里的lable指针指向的字符串虽然小编使用了五个字符,但是实际上表示完之后是4个字符,我们要进行根据cnt的变化来对应完成对字符|/-\的按顺序打印,那么我们可以使用strlen函数(strlen是专门求字符串的长度,遇到’\0’才会停止,求的是’\0’之前的字符个数)求出label指针指向的|/-\的字符个数len,那么接下来我们使用cnt%len,那么不就会随着cnt的++,进而逐个产生0,1,2,3之间的数字吗,我们使用label[cnt%len],不就正好可以去模拟加载旋转的字符了
  2. 剩下的细节注意好每次输出字符串的时候由于没有’\n’的存在,缓冲区不会被刷新,使用fflush强制刷新缓冲区
  3. 注意好使用usleep在每次刷新完缓冲区将字符串显示在屏幕上之后进行休眠50000微秒即可
  4. 最后为了我们的进度条在经过回车之后,在程序结束之后,bash命令行要进行显示,那么就会把我们的进度条给覆盖,为了进度条不被覆盖,我们人为加一个换行即可
  5. printf(“[%-100s][%d%%][%c]\r”,str,cnt,lable[cnt%len]),进行打印编写的时候一定要注意将\r放在最后面,\r会默认将第一个%d输出的位置对齐屏幕的起始位置,但是这里的起始位置由于我们放置了[,所以对齐到[的后面,只有这样才可以正常执行,并且由于%也是一个特殊符号我们输入一个%无法将其正常显示在屏幕上,那么我们需要输入两个%%才可以在屏幕上显示一个%,有人好奇,小编小编,这里你为什么不使用转义字符’\‘呢,因为这个转义字符的使用在linux中可能会出现报错,并且在linux中在屏幕上显示一个特殊字符%主流的写法就是使用两个%%进行编写,同时例如在下载应用的时候想一下进度条通常都是有预留空间的,由于我们的最终是想要在屏幕上打印100个字符’-'作为进度条的最终结束状态,所以这里我们使用[%100s]的方式进行在屏幕上占位100个字符,并且使用[ ]的中间作为我们输出进度条的空间,同时由于占位之后编译器默认是右对齐,不符合我们的阅读习惯,所以我们修改一下默认对齐方式修改成左对齐即[%-100s]即可

完成在这里插入图片描述

#include "progressBar.h"

void progressbar(int speed)
{
	const char* lable="|/-\\";
	char str[102];
	memset(str,'\0',sizeof(str));
	
	int len=strlen(lable);
	int cnt=0;
	
	while(cnt<=100)
	{
		printf("[%-100s][%d%%][%c]\r",str,cnt,lable[cnt%len]);
		fflush(stdout);
	
		str[cnt++]=BODY;
	
		if(cnt<100)
		{
			str[cnt]=RIGHT;
		}                                                                                                                                                    
	
		usleep(speed);
	}
	
	printf("\n");
}

四、进度条小程序plus升级版本

先看效果
在这里插入图片描述
其实这个升级版本的主要作用是接收一个从0开始(注意必须是从0开始,因为字符数组要逐个从0开始使用字符去初始化到100个字符)到100的参数,进而直接给出对应进度条状态,将休眠和循环的设计工作交给了用户来完成可以更为符合用户需求,主要可以用于模拟下载场景,并且使用了回调函数的特性,并且注意当存在连续多次下载的工作的时候要提前对字符数组清空,因为上一次已经将字符数组进行填满了,如果不加清空直接使用,那么最初进度条的状态就已经是满了,具体小编不再展开讲,感兴趣的铁铁们的可以看一下代码实现

1. makefile
progressBar:main.c progressBar.c
		gcc $^ -o $@

.PHONE:clean
clean:
	rm -f progressBar
2. progressBar.h
#pragma once

#include <stdio.h>
#include <unistd.h>
#include <string.h>

#define BODY '-'
#define RIGHT '>'

extern void progressbar(int cnt);
extern void initbar(char* str,int sz);

char str[102];
3. main.c
#include "progressBar.h"

typedef void (*callback_t)(int);

void downLoad(callback_t cb)
{
  int total=1000;
  int cur=0;

  while(cur<=total)
  {
    int rate=cur*100/total;
    
    cb(rate);
    usleep(50000);
    cur+=10;
  }

  printf("\n");
}

int main()
{

  printf("downLoad\n");
  initbar(str,sizeof(str));
  downLoad(progressbar);
  
  printf("downLoad\n");
  initbar(str,sizeof(str));
  downLoad(progressbar);
  
  printf("downLoad\n");
  initbar(str,sizeof(str));
  downLoad(progressbar);

  return 0;
}
4. progressBar.c
#include "progressBar.h"                                                                                                                                 

const char* lable="|/-\\";
void progressbar(int cnt)
{
	if(cnt<0||cnt>100)
	{
		return;
	}

	int len=strlen(lable);
	printf("[%-100s][%d%%][%c]\r",str,cnt,lable[cnt%len]);
	fflush(stdout);
	
	str[cnt++]=BODY;
	
	if(cnt<100)
	{
		str[cnt]=RIGHT;
	}
}

void initbar(char* str,int sz)
{
	memset(str,'\0',sz);
}

总结

以上就是今天的博客内容啦,希望对读者朋友们有帮助
水滴石穿,坚持就是胜利,读者朋友们可以点个关注
点赞收藏加关注,找到小编不迷路!

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

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

相关文章

物流无人机结构与载货设计分析!

一、物流无人机的结构与载货设计模块运行方式 1.结构设计特点 垂直起降与固定翼结合&#xff1a;针对复杂地形&#xff08;如山区、城市&#xff09;需求&#xff0c;采用垂直起降&#xff08;VTOL&#xff09;与固定翼结合的复合布局&#xff0c;例如“天马”H型无人机&am…

【MySQL】表空间结构 - 从何为表空间到段页详解

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;博客仓库&#xff1a;https://gitee.com/JohnKingW/linux_test/tree/master/lesson &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &…

[特殊字符] 免税商品优选购物商城系统 | Java + SpringBoot + Vue | 前后端分离实战项目分享

一、项目简介 本项目为一款功能完备的 免税商品优选购物商城系统&#xff0c;采用 Java 后端 Vue 前端的主流前后端分离架构&#xff0c;支持用户、商家、管理员三类角色&#xff0c;满足商品浏览、下单、商家管理、后台运营等多项功能&#xff0c;适用于实际部署或作为毕业设…

图像处理基础与图像变换

一、目的 通过本次实验&#xff0c;加深对数字图像的理解&#xff0c;熟悉MATLAB中的有关函数&#xff1b;应用DCT对图像进行变换&#xff1b;熟悉图像常见的统计指标&#xff0c;实现图像几何变换的基本方法。 二、内容与设计思想 1、实验内容&#xff1a;选择两幅图像&…

并发笔记-锁(一)

文章目录 1. 基本问题与锁的概念 (The Basic Idea)2. 锁的API与Pthreads (Lock API and Pthreads)3. 构建锁的挑战与评估标准 (Building A Lock & Evaluating Locks)4. 早期/简单的锁实现尝试及其问题 (Early/Simple Attempts)4.1 控制中断 (Controlling Interrupts)4.2 仅…

【Bootstrap V4系列】学习入门教程之 组件-媒体对象(Media object)

Bootstrap V4系列 学习入门教程之 组件-媒体对象&#xff08;Media object&#xff09; 媒体对象&#xff08;Media object&#xff09;一、Example二、Nesting 嵌套三、Alignment 对齐四、Order 顺序五、Media list 媒体列表 媒体对象&#xff08;Media object&#xff09; B…

2025数字中国创新大赛-数字安全赛道数据安全产业积分争夺赛决赛Writeup

文章目录 综合场景赛-模型环境安全-3综合场景赛-数据识别与审计-1综合场景赛-数据识别与审计-2综合场景赛-数据识别与审计-3 有需要题目附件的师傅&#xff0c;可以联系我发送 综合场景赛-模型环境安全-3 upload文件嵌套了多个png图片字节数据&#xff0c;使用foremost直接分离…

无法更新Google Chrome的解决问题

解决问题&#xff1a;原文链接&#xff1a;【百分百成功】Window 10 Google Chrome无法启动更新检查&#xff08;错误代码为1&#xff1a;0x80004005&#xff09; google谷歌chrome浏览器无法更新Chrome无法更新至最新版本&#xff1f; 下载了 就是更新Google Chrome了

数字孪生市场格局生变:中国2025年规模214亿,工业制造领域占比超40%

一、技术深度解析&#xff1a;数字孪生的核心技术栈与演进 1. 从镜像到自治&#xff1a;数字孪生技术架构跃迁 三维重建突破&#xff1a;LiDAR点云精度达2cm&#xff0c;无人机测深刷新频率5Hz&#xff0c;支撑杭州城市大脑内涝预警模型提前6小时预测。AI算法融合&#xff1a…

全球首款无限时长电影生成模型SkyReels-V2本地部署教程:视频时长无限制!

一、简介 SkyReels-V2 模型集成了多模态大语言模型&#xff08;MLLM&#xff09;、多阶段预训练、强化学习以及创新的扩散强迫&#xff08;Diffusion-forcing&#xff09;框架&#xff0c;实现了在提示词遵循、视觉质量、运动动态以及视频时长等方面的全面突破。通过扩散强迫框…

颠覆性技术革命:CAD DWG图形瓦片化实战指南

摘要 CAD DWG图形瓦片化技术通过金字塔模型构建多分辨率地图体系&#xff0c;实现海量工程图纸的Web高效可视化。本文系统解析栅格瓦片与矢量瓦片的技术原理&#xff0c;详细对比两者在生成效率、样式自由度和客户端性能等维度的差异&#xff0c;并结合工程建设、工业设计和智…

不换设备秒通信,PROFINET转Ethercat网关混合生产线集成配置详解

在汽车制造中&#xff0c;连接Profinet控制的PLC&#xff08;如西门子S7&#xff09;与EtherCAT伺服驱动器&#xff08;如倍福AX5000&#xff09;&#xff0c;实现运动控制同步。 在汽车制造的混合生产线集成中&#xff0c;实现西门子S7 PLC与倍福AX5000 EtherCAT伺服驱动器的…

c++STL-string的使用

这里写自定义目录标题 string的使用string写成类模板的原因string的版本举例构造、析构函数和赋值重载构造函数和析构函数operator Iterators迭代器begin和endrbegin和rendcbegin和cend&#xff0c;crbegin和crend&#xff08;c11&#xff09; capacity容量有关函数不同编译器下…

UNet网络 图像分割模型学习

UNet 由Ronneberger等人于2015年提出&#xff0c;专门针对医学图像分割任务&#xff0c;解决了早期卷积网络在小样本数据下的效率问题和细节丢失难题。 一 核心创新 1.1对称编码器-解码器结构 实现上下文信息与高分辨率细节的双向融合 如图所示&#xff1a;编码器进行了4步&…

使用 SHAP 进行特征交互检测:揭示变量之间的复杂依赖关系

我们将探讨如何使用 SHAP&#xff08;SHapley 加法解释&#xff09;来检测和可视化机器学习模型中的特征交互。了解特征组合如何影响模型预测对于构建更透明、更准确的模型至关重要。SHAP 有助于揭示这些复杂的依赖关系&#xff0c;并使从业者能够以更有意义的方式解释模型决策…

Python-MCPInspector调试

Python-MCPInspector调试 使用FastMCP开发MCPServer&#xff0c;熟悉【McpServer编码过程】【MCPInspector调试方法】-> 可以这样理解&#xff1a;只编写一个McpServer&#xff0c;然后使用MCPInspector作为McpClient进行McpServer的调试 1-核心知识点 1-熟悉【McpServer编…

Java设计模式-策略模式(行为型)

策略模式详解 一、策略模式概述 1.1 基本概念 策略模式是一种行为型设计模式&#xff0c;它主要用于处理算法的不同变体。其核心思想是将算法的定义与使用分离开来&#xff0c;把一系列具体的算法封装成独立的策略类&#xff0c;这些策略类实现相同的策略接口。客户端可以在…

html body 设置heigth 100%,body内元素设置margin-top出滚动条(margin 重叠问题)

今天在用移动端的时候发现个问题&#xff0c;html,body 设置 height&#xff1a;100% 会出现纵向滚动条 <!DOCTYPE html> <html> <head> <title>html5</title> <style> html, body {height: 100%; } * {margin: 0;padding: 0; } </sty…

C语言模糊不清的知识

1、malloc、calloc、realloc的区别和用法 malloc实在堆上申请一段连续指定大小的内存区域&#xff0c;并以void*进行返回&#xff0c;不会初始化内存。calloc与malloc作用一致&#xff0c;只是calloc会初始化内存&#xff0c;自动将内存清零。realloc用于重新分配之前通过mallo…

如何配置光猫+路由器实现外网IP访问内部网络?

文章目录 前言一、网络拓扑理解二、准备工作三、光猫配置3.1 光猫工作模式3.2 光猫端口转发配置&#xff08;路由模式时&#xff09; 四、路由器配置4.1 路由器WAN口配置4.2 端口转发配置4.3 动态DNS配置&#xff08;可选&#xff09; 五、防火墙设置六、测试配置七、安全注意事…