当前位置: 首页 > news >正文

【Linux】倒计时和进度条实现

目录

  • 前言
  • 一、知识铺垫
    • 1. 回车换行
    • 2. 缓冲区
  • 二、倒计时小程序
  • 三、进度条小程序
    • 1. 进度条理论代码
    • 2. 进度条实战版本

前言

【Linux】自动化构建–make/Makefile详情请点击,今天继续介绍【Linux】倒计时小程序和进度条程序

一、知识铺垫

1. 回车换行

回车代表的意思是让光标回到当前行的起始位置,换行是换到下一行的意思

  • 我们使用"\r"表示回车,"\n"表示换行

2. 缓冲区

  1. 我们在test.c中写入下面代码,sleep(2):休眠2秒,sleep头文件是#include< unistd.h >
    在这里插入图片描述
  2. 使用gcc编译链接再运行,发现开始的时候没有显示"hello world",等待2s后再显示屏上打印"hello world",按照我们正常C语言逻辑我们可以知道,程序是从上到下一条条执行的,按照正常逻辑应该先执行"hello world",在sleep 2s,然后程序结束,为什么会是我们看到的那样呢?
  3. 程序后面能打印出"hello world"说明字符串并没有丢失,而是先被保存起来了,这个保存的位置叫做缓冲区,当程序遇到"\n"或者程序结束时会将缓冲区的内容在显示屏显示出来,由于printf函数后面没有"\n",所以该语句暂时保存在缓冲区,sleep 2s后程序结束输出到显示屏上
  4. 当在"hello world"语句后面加入"\n"后,先在显示屏输出"hello world",再sleep 2s,程序结束
    在这里插入图片描述
  5. 如果在不加"\n"的情况下,如何让程序立刻输出"hello world",再sleep 2s,程序结束?
  • 可以使用fflush函数强制刷新缓冲区内容,fflush需要传对应的流,流分为:标准输入流(stdin)、标准输出流(stdout)、标准错误流
  • “hello world"是要输出到显示屏上,因此传入标准输出流,使用fflush后先输出"hello world”,再sleep 2s后程序结束,且没有换行
    在这里插入图片描述
    在这里插入图片描述

二、倒计时小程序

  1. 我们默认生成10s倒计时
  2. 使用while循环来打印的倒计时数字并设置sleep,这样才能看到倒计时效果,注意这里需要使用fflush函数强制刷新缓冲区内容到显示屏上
  3. 数字是以字符显示到显示屏上的,数字10在显示屏打印出来时是字符1和字符0打印到显示屏上,当倒计时数字是9时,是一个字符,那么0那个字符并不会被覆盖,因此我们要使用%-2d让数字打印占两个字符,且左对齐打印
  4. 最后倒计时完毕后加入换行符,防止倒计时的0被命令行覆盖
 #include<stdio.h>#include<unistd.h>int main(){int cnt = 10;while(cnt >= 0){printf("%-2d\r", cnt);fflush(stdout);sleep(1);                                                                                             cnt--;}printf("\n");return 0;}

三、进度条小程序

进度条样例
在这里插入图片描述

1. 进度条理论代码

  1. 我们创建processBar.c文件编写进度条代码的实现,main.c文件编写进度条函数和基本的框架,processBar.h声明进度条函数。同时使用make/makefile自动化构建
  2. processBar.h中,为了防止头文件被重复包含,使用#pragma once,同时声明进度条函数void Process()
  3. 包含头文件#include<string.h>和#include<unistd.h>,在初始化processbuff时使用memset需要string头文件,使用usleep时需要unistd头文件
#pragma once
#include <stdio.h>
#include<string.h>
#include<unistd.h>   void Process();
  1. processBar.c中,包含#include<processBar.h>,宏定义数组大小和加载符号
  2. 根据上面进度条实例,我们需要打印processbuff、进度百分比和加载符,同时要使用fflush函数强制缓冲区刷新,实时将进度更新到显示屏上,再useep(50000)
  3. 最后进度条更新到100%后换行,防止命令行覆盖进度条
#include"processBar.h"#define SIZE 101
#define STYLE '='
void Process()
{const char* label = "|/-\\";int len = strlen(label);char processbuff[101];memset(processbuff, '\0', SIZE);int cnt = 0;while(cnt <= 100){printf("[%-100s][%d%%][%c]\r", processbuff, cnt, label[cnt%len]);fflush(stdout);processbuff[cnt++] = STYLE;usleep(50000);}printf("\n");}     
  1. main.c中,也需要包含#include<processBar.h>,直接调用Process函数
 #include"processBar.h"int main()
{Process();                                                                                                return 0;
}

2. 进度条实战版本

生活中,进度条往往运用在软件下载过程中,由于网速和软件包大小不同软件下载时间也是不同的,进度条速度也在实时变化

  1. processBar.h中,为了防止头文件被重复包含,使用#pragma once,同时声明进度条函数void FlashProcess(double total,double cur)
  2. 包含头文件#include<string.h>和#include<unistd.h>,在初始化processbuff时使用memset需要string头文件,使用usleep时需要unistd头文件,使用#include<time.h>和#include<stdlib.h>生成随机数来模拟下载网速波动
#pragma once
#include <stdio.h>
#include<string.h>
#include<unistd.h>
#include<time.h>
#include<stdlib.h>  void FlashProcess(double total,double cur); // 更新进度,按照实时下载进度更新进度条
  1. processBar.c中,包含#include<processBar.h>,宏定义数组大小和加载符号
  2. 对于进度条进度‘=’的更新问题,由于等号不可能出现0.13等小数个等号,所以取整
  3. 对于进度条的旋转光标的实现,在正常下如果下载较慢(进度条不更新,rate也没有更新),怎么判断是否还在下载,还是说只是下载较慢,暂时没有更新。通过旋转光标是否转动来判断,所以旋转光标的转换不能和total和cur挂钩,而是和调用FlashProcess函数的次数来更新,只要还在调用该函数说明还在下载中
  4. 再将进度条实时刷新到显示屏上,而不是等函数调用完成之后自动刷新到显示屏上,所以使用fflush(stdout);
  5. 当进度条到达100%之后,还需要换行,避免命令行覆盖进度条
  1 #include"processBar.h"2 3 4 #define SIZE 1015 #define STYLE '='8 void FlashProcess(double total,double cur)9 {10     if(cur > total)11         cur = total;12     double rate = cur / total * 100; //转化为0.1->10%这样的形式13     int cnt = (int) rate;// 10.4->1014     char processbuff[SIZE];15     memset(processbuff, '\0', SIZE);16     int i = 0;17     for(; i < cnt; i++)18     {19         processbuff[i] = STYLE;20     }21     static const char* label = "|/-\\";22     static int index = 0;23     printf("[%-100s][%.lf%%][%c]\r",processbuff, rate, label[index++]);                                       24     index %= strlen(label);25     fflush(stdout);26     if(cur >= total)27         printf("\n");28 }
  1. main.c中,也需要包含#include<processBar.h>,需要一个下载函数,当cur > total时,将cur = total,再刷新到显示屏上跳出循环
  2. 模拟实现网速波动使用函数SpeedFloat,限制网速波动范围
  1 #include"processBar.h"5 double SpeedFloat(double start, double range)6 {7     int int_range = (int)range;8     return start + rand() % int_range + (range - int_range);9 10 }11 void Download(double total)12 {13     srand(time(NULL));14     double cur = 0.0;15     while(1)16     {17         if(cur > total)18         {19             cur = total;20             FlashProcess(total, cur);21             break;22         }23         FlashProcess(total, cur); // 更新进度,按照实时下载进度更新进度条25         cur += SpeedFloat(speed, 20.3);26         usleep(30000);                                                                                        27     }28 }30 int main()31 {32     printf("Download:20.0MB\n");33     Download(20.0);34     printf("Download:200.0MB\n");35     Download(200.0);36     printf("Download:2000.0MB\n");37     Download(2000.0);38     printf("Download:20000.0MB\n");39     Download(20000.0);40     return 0;41 }
  1. 我们还可以定义函数指针在调用Download函数的时候直接调用进度条更新函数Download(double total, callback_t cb)
  5 //函数指针类型  6 typedef void (* callback_t)(double, double); 14 //cb:回调函数                 15 void Download(double total, callback_t cb)16 {                              17     srand(time(NULL));         18     double cur = 0.0;                                                                                         19     while(1)                   20     {                          21         if(cur > total)        22         {                      23             cur = total;24             cb(total, cur);25             break;26         }27         cb(total, cur); // 更新进度,按照实时下载进度更新进度条28        // cur += speed; //模拟下载29         cur += SpeedFloat(speed, 20.3);30         usleep(30000);31     }32 }34 int main()35 {36     printf("Download:20.0MB\n");                                                                              37     Download(20.0, FlashProcess);38     printf("Download:200.0MB\n");39     Download(200.0, FlashProcess);40     printf("Download:2000.0MB\n");41     Download(2000.0, FlashProcess);42     printf("Download:20000.0MB\n");43     Download(20000.0, FlashProcess);44     return 0;45 }

运行结果如下:模拟实现了不同网速下的进度条下载过程
在这里插入图片描述

http://www.dtcms.com/a/419285.html

相关文章:

  • 网站建设需要用到哪些软件有哪些系统安装wordpress
  • 梯度下降(Gradient Descent)
  • 东莞市建设规划局网站游戏类企业网站模板
  • C++---bind(绑定函数或函数对象的参数)
  • 网站和域名网站开发技术是什么
  • 个人如何开网站西安网络推广外包公司
  • 国产处理器飞腾CPU各系列综合性能对比
  • 南宁网站设计推广wordpress+授权登录
  • 网站建设深圳哪里学品牌建设提升
  • 《LangChain入门指南》学习笔记1:第1章 LangChain:开启大语言模型时代的钥匙
  • 国清汇携手社保基金会推出《国脉相承·传世养老基金》
  • 3、内存系统详解 - 从DDR演进到GPU内存架构的认知基石
  • 芯片和半导体:Intel开始布局14A工艺
  • JavaWeb 课堂笔记 —— 26 SpringBoot 原理
  • 网上国网app下载安装哈尔滨seo优化排名
  • HTTP首部字段(速查-全47种)
  • 嘉兴高端网站定制100网站建设
  • TypeScript的新类型:unknown
  • MacOS 使用ssh2-python报错ImportError: dlopen ... _libssh2_channel_direct_tcpip_ex
  • 天蓝色美容网站扶贫基金会网站建设是哪家公司
  • 大模型离线部署docker(推荐) + dify部署(docker)
  • 如何基于源码快速搭建数字药店系统?药店买药APP开发实战指南
  • 网站开发文档范例赣榆网站建设xxiaoseo
  • 用生活中的实例解释java的类class和方法public static void main
  • Java SE “概念与优势”面试清单(含超通俗生活案例与深度理解)
  • wordpress发布站点wordpress 链接微博
  • 2025 AI 产业:技术趋势、伦理治理与生态重构
  • 网站开发用到什么技术南昌房产网官方
  • 2025年HTTP代理实测报告:速度、稳定性、价格深度对比
  • Docker 使用技巧:从效率优化到生产级实践(含命令示例)