【Linux】实现进度条小程序

news2024/9/25 17:12:20

个人主页 : zxctscl
如有转载请先通知

文章目录

  • 1. 前言
  • 2. 回车和换行
  • 3. 缓冲区
  • 4. 进度条
    • 4.1 倒计时设置
    • 4.2 进度条
      • 4.2.1 实现简单进度条
      • 4.2.2 进度条完善
  • 5. 附进度条代码
    • 5.1 Processbar.h
    • 5.2 Processbar.c
    • 5.3 Main.c
    • 5.4 Makefile

1. 前言

在之前已经了解了 【Linux】vim的使用和 【Linux】编译器-gcc/g++使用还有 【Linux】自动化构建工具-make/Makefile,有了这些工具,这次来实现一个进度条小程序。

2. 回车和换行

换行:是换到新的一行。
回车:是回到最开始。

举个例子:在格子里面写字的时候,第一行写完,要到第二行,此时到的第二行的结尾,这个叫换行。而从第二行结尾回到第二行开头是回车。
也可以先回车到第一行的开始,再换行到第二行。
在这里插入图片描述
回车和换行是两个动作。

在老式键盘上面就很明显,而现在的键盘为了省空间就不这样了:
在这里插入图片描述

平时在C语言上用到的“\n”叫回车换行,既回车,又换行。
如果想让只回车就用到"\r"
有的代码用"\r\n"表示回车换行,如果在"\r""\n"同时存在时,"\n"只是换行。

在老式打字机上面就会有下面这样的拨片,当打完一行之后,得手动把它往回拨,一拨纸就往上走(换行),写入位置就往左走,对应就是回车。

在这里插入图片描述

3. 缓冲区

在代码里面把"\n"去掉:
在这里插入图片描述
在编译过程中就会发现,再休眠3秒的时候这个程序并没有输出,而是当程序结束的时候程序才输出。
在这里插入图片描述
"\n"消息就直接显示出来,然后再sleep。
不加"\n"这个字符串打印就没有显示出来,先sleep,再到程序退出的时候才显示这个字符串。
在这里插入图片描述

那么在不加"\n"那么printfsleep哪个先运行呢?
C语言在执行代码时候,默认从上往下执行,这个叫顺序结构。
printf只是没有把数据在显示器上显示出来,并不是没有执行。只是在sleep期间这个字符串没有显示出来而已。

那么在sleep期间字符串在哪里呢?
它被保存到缓冲区里面。它就是一块内存空间。
printf的时候,把字符串拷贝到缓冲区里面,然后定期把数据刷新到显示器上面,此时就能看到这个字符串了。
不带"\n"的时候,字符串就在缓冲区里,当return 0时,程序结束时,一般要自动冲刷缓冲区。

想要在程序结束之前就刷新缓冲区,有3种方式:
1. "\n"直接就把缓冲区数据就刷出来了。包含"\n"之前的全部刷新出来。
举个例子:
在这里插入图片描述
会发现先出来"\n"之前的,剩下的程序结束才出来:
在这里插入图片描述

2. 缓冲区满了进行刷新
3. 强制刷新。
ffush把特定文件流进行刷新:
在这里插入图片描述
在Linux下一切皆文件,可以把显示器当文件看。
在C语言中程序在启动时默认会打开三个输入输出流:
stdin对应的设备是键盘,stdoutstderr对应的是显示器。
在这里插入图片描述
在系统中不管是设备还是文件一律都是FILE。
一般打印输出用到的是stdout,显示到显示器上。

为什么会默认打开这输入输出流?
方便用户进行输入和输出。一般使用计算机的都有输入和输出的需求,所以一般就默认打开输入输出流,就不用在写代码打开上面键盘和显示器这些设备了。

在代码中使用一下fflush

  1 #include<stdio.h>
  2 #include<unistd.h>
  3
  4 int main()
  5 {
  6   printf("hello world,hello...");
  7   fflush(stdout);
  8   sleep(3);
  9   return 0;
 10 }

在这里插入图片描述
编译发现缓冲区内容就直接冲刷出来了:
在这里插入图片描述
在这里插入图片描述
为什么会存在缓冲区?
缓冲区提高了用户效率。以前的printf是往硬件上写的,现在直接写到内存了。从内存拷贝内存数据的效率,肯定比从硬件拷贝到内存的效率高。
它刷新的次数越少,单次刷新的数据量越大,效率越高。
按行刷新是方便用户阅读。

4. 进度条

4.1 倒计时设置

假设将格子是光标的位置,一般在输入的时候就会是下面这样的:
在这里插入图片描述
但是如果想要实现光标在同一个位置,实现倒计时的感觉,就行下面这样:用8会覆盖这个9。
在这里插入图片描述
但是8会覆盖这个9后,光标会往后走,想要把在8的位置输出7,光标就得回到8的位置,7就把8覆盖,依此类推,就能实现一个动态的倒计时。
就是在同一个位置不停的覆盖,就能实现动态效果。
在这里插入图片描述
用代码来实现一下倒计时的感觉:
在这里插入图片描述
但这个代码输出并不是我们所想要的输出:
在这里插入图片描述

------------------------------------------------------------------------------------------

来修改一下代码,加上"\r":
在这里插入图片描述
这里发现暂停一段时间,数据并没有显示出来:
在这里插入图片描述
"\r"相当于我们写了一个数回到最开始,就清了一个数,所以最后什么也不显示。

------------------------------------------------------------------------------------------

那就直接加一个强制刷新缓冲区:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3
  4 int main()
  5 {
  6   int count=9;
  7   while(count>=0)
  8   {
  9     printf("%d\r",count);
 10     fflush(stdout);
 11     count--;
 12     sleep(1);
 13   }
 14   return 0;
 15 }

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

------------------------------------------------------------------------------------------

既然能够覆盖一个字符,那么肯定也能覆盖一个字符串。

  1 #include<stdio.h>
  2 #include<unistd.h>
  3
  4 int main()
  5 {
  6   int count=9;
  7   while(count>=0)
  8   {
  9     printf("倒计时:%d\r",count);
 10     fflush(stdout);
 11     count--;
 12     sleep(1);
 13   }
 14   printf("\n");
 15   return 0;
 16 }

来看看效果图:
在这里插入图片描述
在这里插入图片描述
如果从10开始:
在这里插入图片描述
就会出现这样的效果:
在这里插入图片描述
数字10,实际在显示器上显示的是字符,它转化成1字符和0字符。当在打印的9时候字符长度变短了,0就没有办法覆盖,就会一直在。
所以这里用%2d:
在这里插入图片描述
这时候就没有问题了:
在这里插入图片描述

4.2 进度条

这里用多文件来实现,Processbar.h用来声明,Processbar.c用来实现方法,Main.c用来调用Processbar.c里面的方法,再使用Makefile来实现自动化调用。
在这里插入图片描述

先写出基本的框架逻辑:
在这里插入图片描述

在这里插入图片描述

在编译的时候不用.h文件,因为在.c文件中已经包含.h是在当前目录下的,在编译时候会展开头文件的。
在Makefile里面写:

  1 processbar:Main.c Processbar.c
  2   gcc -o $@ $^ 
  3 .PHONY:clean
  4 clean:
  5   rm -f processbar

测试一下代码:
在这里插入图片描述

4.2.1 实现简单进度条

先画出进度条的示例:
进度条在增加的同时,当前的进度也在变化,光标也在不停的旋转。
在这里插入图片描述

这个进度条实现的时候,缓冲区的长度从0%到100%,但是还得考虑"\0",所以长度定义为101。
把缓冲区清空就用到memset
在这里插入图片描述

想要在缓冲区里面写特殊符号,就直接用define:#define Style '#'

用循环来实现动态进度条打印,直接打印相对应的字符串,和倒计时一样用fflush(stdout);来刷新缓冲区,随着时间的增加,进度条也在不断增加:
在这里插入图片描述
来看看效果:
在这里插入图片描述
发现这里打印时间太慢了。

使用usleep,它休眠的时间比sleep的小,所以这里就用usleep来进行休眠。
在这里插入图片描述
然后将字符串输出改为左对齐,加上进度条对应的比率:
在这里插入图片描述

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

4.2.2 进度条完善

但是一般进度条不会单独出现,只有当我们下载一个文件同时出现。
这里就先模拟下载过程,就在在Main.c写一个download来实现。一般在下载一个文件的时候,会有下载文件的大小和下载到多少,和网络的带宽。
分别用变量定义一下文件大小,当前下载进度和带宽:

double filesize = 1024*1024*1024*1.0;
double current = 0.0; 
double bandwidth = 1024*1024*1.0;

还可以加上一个开始下载的提示:

printf("download begin,current: %lf\n",current);

和下载完成的提示:


printf("\ndownload done,filesize: %lf\n",filesize);

在下载过程中把要下载的文件大小,和目前已经下载的大小传给进度条ProcBar,让进度条时时交互。
在这里插入图片描述
Processbar.h中记得把在Processbar.c使用的打印进度条函数声明一下:

void ProcBar(double total,double current);

在这里插入图片描述
Processbar.c中,就和上面的简单实现进度条一样,把文件的长度,和目前下载的长度传进去:

void ProcBar(double total,double current)

这里加了当前下载的进度百分比
double rate=(current*100.0)/total;
在循环的时候得将前下载的进度输出,循环的时候得把double rate的类型转为int

int loop_count=(int)rate;

最后打印出当前下载的进度,还得冲刷缓冲区:

  printf("[%-100s][%.1lf%%][%c]\r",bar,rate,lable[cnt%len]);
  fflush(stdout);

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

在这里插入图片描述
Processbar.h中定义一个函数指针类型:

typedef void(*callback_t)(double,double);

然后在Main.c里面将download改一下,可以根据文件的大小来下载:

void download(double filesize,callback_t cb)

在download函数里面直接执行:cb(filesize,current);方法。
为什么要这么写?
在之后如果用户写一个图形化界面的进度条,就能在下载的时候同时更新图形化界面。
在这里插入图片描述

也可以让进度条加上颜色,只需要在网上找一个关于用C语言输出有颜色相关的内容也就会有了。
这里是加了颜色效果:

 printf("\033[40;44m[%-100s][%.1lf%%][%c]\r\033[0m",bar,rate,lable[cnt%len]);

在这里插入图片描述

在这里插入图片描述

5. 附进度条代码

5.1 Processbar.h

  1 #pragma once
  2
  3 #include<stdio.h>
  4
  5 typedef void(*callback_t)(double,double);
  6 void ProcBar(double total,double current);
  7 //extern void ForTest();


5.2 Processbar.c

  1 #include "Processbar.h"
  2 #include <string.h>
  3 #include <unistd.h>
  4
  5 #define Length 101
  6 #define Style '#'
  7
  8 const char *lable = "|/-\\";
  9
 10 
 11 void ProcBar(double total,double current)
 12 {
 13   char bar[Length];
 14   memset(bar,'\0',sizeof(bar));
 15   int len=strlen(lable);
 16 
 17   int cnt = 0;
 18   double rate=(current*100.0)/total;
 19   int loop_count=(int)rate;
 20   while(cnt<=loop_count)
 21   {
 22     bar[cnt++]=Style;
 23 
 24   }
 25 
 26    //没有加颜色前的输出 printf("[%-100s][%.1lf%%][%c]\r",bar,rate,lable[cnt%len]);
        printf("\033[40;44m[%-100s][%.1lf%%][%c]\r\033[0m",bar,rate,lable[cnt%len]);
 27     fflush(stdout);
 28 }

5.3 Main.c

  1 #include"Processbar.h"
  2 #include <unistd.h>
  3
  4 double bandwidth = 1024*1024*1.0;
  5 void download(double filesize,callback_t cb)
  6 {
  7   double current = 0.0;
  8   
  9
 10   printf("download begin,current: %lf\n",current);
 11   while(current<=filesize)
 12   {
 13     cb(filesize,current);
 14     usleep(100000);
 15     current+=bandwidth;
 16
 17   }
 18   printf("\ndownload done,filesize: %lf\n",filesize);
 19 }
 20
 21
 22 int main()
 23 {
 24   download(101*1024*1024,ProcBar);
 25  // ProcBar(100.0,56.9);
 26
 27 // ProcBar(100.0,1.0);
 28  // ProcBar(100.0,99.9);
 29
 30  // ProcBar(100.0,100);
 31   //ForTest();
 32   return 0;
 33 }
~

5.4 Makefile

  1 processbar:Main.c Processbar.c
  2   gcc -o $@ $^ 
  3 .PHONY:clean
  4 clean:
  5   rm -f processbar

有问题请指出,大家一起进步吧!!!

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

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

相关文章

C++ list详解及模拟实现

目录 本节目标 1. list的介绍及使用 1.2 list的使用 2.list的模拟实现 1.对list进行初步的实现 2.头插和任意位置的插入 3.pos节点的删除&#xff0c;头删&#xff0c;尾删 4.销毁list和析构函数 5.const迭代器 6.拷贝构造和赋值操作 3.完整代码 本节目标 1. list的…

怎么做扫码签到活动_一场别开生面的活动签到革新之旅

在数字化飞速发展的今天&#xff0c;传统的签到方式已无法满足人们对高效、便捷、互动性的追求。为此&#xff0c;我们创新性地推出了扫码签到活动&#xff0c;为您带来一场前所未有的智慧互动新体验。 工具/原料 微信小程序 飞多多网站 方法/步骤 一、扫码签到&#xff0c…

【目标跟踪】奇葩需求如何处理(二)

文章目录 一、前言二、奇葩需求2.1、井盖2.2、管线 三、后记 一、前言 在工作中往往出现些奇葩需求。上一篇介绍了一些奇葩需求奇葩需求如何处理&#xff08;一&#xff09; &#xff0c;今天给大家分享一些更奇葩的需求。 二、奇葩需求 2.1、井盖 昨天突然接到一个需求&…

JAVA_会话

会话技术 1.会话: 一次会话包含多次请求和响应 2.功能: 在一次会话的范围内的多次请求&#xff0c;共享数据 3.方式: 3.1.客户端会话技术 Cookie(甜点) 1.概念: 客户端会话技术,将数据保存到客户端 2.快速入门: 1.创建Cookie对象,绑定数据new Cookie(String name,String v…

msvcp140.dll是什么文件?msvcp140.dll丢失如何解决(最新教程)

在玩电脑的时候&#xff0c;经常会碰到一些烦人的东西&#xff0c;比如那个“msvcp140.dll丢失”啥啥啥的。这个东西一出现&#xff0c;整个人都不好了&#xff0c;完全影响了我们愉快电脑生活的节奏。为啥会出现msvcp140.dll丢失的这种情况&#xff0c;怎么解决&#xff0c;还…

精读《架构设计之 DCI》

本期精读文章是&#xff1a;The DCI Architecture 1 引言 随着前端 ES6 ES7 的一路前行&#xff0c; 我们大前端借鉴和引进了各种其他编程语言中的概念、特性、模式; 我们可以使用函数式 Functional 编程设计&#xff0c;可以使用面向对象 OOP 的设计&#xff0c;可以使用面向…

【C++从练气到飞升】04---拷贝构造函数

&#x1f388;个人主页&#xff1a;库库的里昂 ✨收录专栏&#xff1a;C从练气到飞升 &#x1f389;鸟欲高飞先振翅&#xff0c;人求上进先读书。 目录 ⛳️推荐 一、拷贝构造函数的引入 1. 以日期类为例:进行的值拷贝是不会发生错误的 2. 以栈类为例:进行的值拷贝会发现发…

C语言基础(十六)通过指针来输入和获取结构体的变量值

老样子&#xff0c;先看代码 #include <stdio.h> #include <string.h>#define NLEN 30 struct namect{char fname[NLEN];char lname[NLEN];int letters; };void getinfo(struct namect *); void makeinfo(struct namect *ptr); void showinfo(const struct namec…

Kubernetes的Namespace使用

在 Kubernetes 中&#xff0c;命名空间提供了一种用于隔离单个集群中的资源组的机制。资源名称在命名空间内必须是唯一的&#xff0c;但不能跨命名空间。基于命名空间的作用域仅适用于命名空间物体 &#xff08;例如部署、服务等&#xff09;而不是集群范围的对象&#xff08;例…

牛客周赛 Round 37VP(DEF)

D.思维题&#xff1a; 若按照顺序发现很难入手&#xff0c;于是我们不妨先小紫&#xff0c;再让小红反悔即可 假设为cabababbabazbc&#xff0c;如果直接小紫&#xff0c;那么它一定以a开头&#xff0c;于是小红可以先把首尾的a去掉&#xff0c;即czbc,此时可以得到bc,于是小红…

19---时钟电路设计

视频链接 时钟硬件电路设计01_哔哩哔哩_bilibili 时钟电路设计 晶振是数字电路的心脏&#xff0c;数字电路需要一个稳定的工作时钟信号&#xff0c;时钟电路至关重要&#xff01; 1、晶振概述 晶振一般指晶体振荡器。晶体振荡器是指从一块石英晶体上按一定方位角切下薄片&…

基于stable diffusion的IP海报生成

【AIGC】只要10秒&#xff0c;AI生成IP海报&#xff0c;解放双手&#xff01;&#xff01;&#xff01;在AIGC市场发展的趋势下&#xff0c;如何帮助设计工作者解放双手。本文将从图像生成方向切入&#xff0c;帮助大家体系化的学习Stable diffusion的使用&#xff0c;完成自有…

sonar接入maven项目

1、介绍 sonar是一款静态代码质量分析工具&#xff0c;支持Java、Python、PHP、JavaScript、CSS等25种以上的语言&#xff0c;而且能够集成在IDE、Jenkins、Git等服务中&#xff0c;方便随时查看代码质量分析报告。他有如下特性 (1) 检查代码是否遵循编程标准&#xff1a;如命…

【回归预测】基于DBO-BP(蜣螂优化算法优化BP神经网络)的回归预测 多输入单输出【Matlab代码#68】

文章目录 【可更换其他算法&#xff0c;获取资源请见文章第6节&#xff1a;资源获取】1. BP神经网络2. 蜣螂优化算法3. DBO-BP神经网络模型的构建4. 部分代码展示5. 仿真结果展示6. 资源获取 【可更换其他算法&#xff0c;获取资源请见文章第6节&#xff1a;资源获取】 1. BP神…

[云] vmware: host: net: Net.CoaleseDefaultOn

https://communities.vmware.com/t5/Storage-Performance/Advanced-Networking-Performance-Options/ta-p/2792649 在vsphere client下的路径是&#xff1a; 选择使用的host -> 右键setting->configure-> system->advanced system setting->edit->Net.Coales…

第九节HarmonyOS 常用基础组件31-Toggle

1、描述 组件提供勾选框样式、状态栏样式以及开关样式。 2、子组件 仅当ToggleType为Button时可包含子组件。 3、接口 Toggle(options: { type: ToggleType , isOn?: boolean}) 4、参数 参数名 参数类型 必填 描述 type ToggleType 是 开关的样式。 isOn boole…

蓝桥杯 第3217题 简单的异或难题 C++ Java Python

题目 思路和解题方法 计算给定数组中子数组异或和的问题。它采用了前缀异或的方法来预处理数组&#xff0c;然后对于每个查询&#xff0c;通过异或操作计算子数组的异或和。 读取输入的数组&#xff0c;并计算每个位置的前缀异或和。对于每个查询&#xff0c;读取查询的左右边界…

一文读懂MES和ERP的区别

MES&#xff08;Manufacturing Execution System&#xff09;系统是制造执行系统&#xff0c;位于上层的计划管理系统与生产过程的直接工业控制系统之间&#xff0c;是面向车间层的管理信息系统&#xff0c;能够对整个车间制造过程进行优化&#xff0c;实时收集生产过程中的数据…

python 爬虫 地理空间DEM 制作中国地形

一.配置Python 爬虫 环境 from selenium import webdriver import time # from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.by import Byfrom selenium.webdriver.common.keys import Keys # from selenium.webdriver.comm…

Java毕业设计-基于springboot开发的乐校园二手书交易管理系统-毕业论文+答辩PPT(附源代码+演示视频)

文章目录 前言一、毕设成果演示&#xff08;源代码在文末&#xff09;二、毕设摘要展示1、开发说明2、需求分析3、系统功能结构 三、系统实现展示1、系统功能模块2、管理员功能模块3、卖家用户功能模块4、用户功能模块 四、毕设内容和源代码获取总结 Java毕业设计-基于springbo…