Linux平台下实现的小程序-进度条

目录

1.换行、回车概念

2.缓冲区

2.1缓冲区

2.2强制刷新

3.进度条程序

Makefile文件

ProgressBar.h

ProgressBar.c

Main.c

执行结果


1.换行、回车概念

/n:换行+回车(\r:回车)

2.缓冲区

如下图在vim编辑器中的命令模式下输入命令,在3号手册中查看sleep。

sleep是由Linux提供的接口,用于程序在执行时停下来休眠数秒。


如下图在命令行窗口中输入命令,在3号手册中查看usleep。

usleep是由Linux提供的接口,用于程序在执行时停下来休眠数微秒。

sleep与usleep的区别是sleep休眠时间单位是秒,usleep休眠时间单位是微秒。

1秒=1000毫秒=1000 000微秒=1000纳秒

2.1缓冲区

情况一、加上\n

运行结果:先打印字符串换行休眠三秒再打印命令行提示符


情况二、不加\n

运行结果:休眠三秒然后打印出字符串和命令行提示符

出现以上两种不同的情况是因为printf()函数不是直接向显示器文件写入,而是先向缓冲区中写入。

  1. 由键盘输入字符也是会立即显示到屏幕上的。
  2. 之前printf函数是向磁盘中写入,然后再向显示器中写入,现如今为了提高效率,向内存中写入而不是向磁盘中写入(由内存向内存拷贝数据要比由内存向磁盘拷贝数据要快);
  3. 由缓冲区向显示器中刷新,单次刷新量越大刷新次数越少,效率越高,但一次刷新太多用户看不过来,对于我们人来说习惯于按行读。综合来说按行刷新是最合理的。

2.2强制刷新

C语言中fflush函数用来强制将数据刷新到显示器上。

每一个C语言程序在执行开始之前会默认打开如下3个流:

  1. FILE* stdin:是标准输入流,对应的设备是显示器;
  2. FILE* stdout:是标准输出流,对应的设备是键盘;
  3. FILE* stderr:是标准错误流,对应的设备是显示器。

为什么C语言在开始执行程序之前会打开这3个标准流呢?

因为程序对大多数用户来说是用来做计算的,用户由键盘输入,经过程序计算,再由显示器给用户显示出来,显示器和键盘被用户经常使用,那C语言设计者就想既然显示器和键盘被多次用,那在程序开始执行之前默认将其打开。

3.进度条程序

Makefile文件

cpp 复制代码
ProgressBar.exe:Main.c ProgressBar.c
  gcc $^ -o $@ -std=c99
PHONY:clean
clean:
  rm -f ProgressBar.exe 

ProgressBar.h

cpp 复制代码
#pragma once
#include <stdio.h> 

void ProBar1();    
void ProBar2(double fileSize, double current);    

ProgressBar.c

cpp 复制代码
#include "ProgressBar.h"
#include <unistd.h>
#include <string.h>

//void test()
//{
//  printf("hello\n");
//}
  
#define STYLE '='
#define LENGTH 101

//version 1
void ProBar1()
{
  char bar[LENGTH];
  memset(bar,'\0',LENGTH);
  char state[]={'|','/','-','\\'};
 
  int cnt=0;
  while(cnt<=100)
  {
    printf("[%-100s][%3d%%][%c]\r",bar,cnt,state[cnt%4]);
    fflush(stdout);
    bar[cnt++] = STYLE;
    usleep(50000);
  }
  printf("\n");
} 

//version 2
void ProBar2(double fileSize, double current)
{                                                                                                                                                                                                            
   double rate = (current*100.0) / fileSize; 
   int loopCount = (int)rate;
   char bar[loopCount+1];
   memset(bar,STYLE,loopCount);
   bar[loopCount] = '\0';
  
   char state[]={'|','/','-','\\'};
  
   printf("[%-100s][%.1lf%%][%c]\r",bar,rate,state[loopCount%4]);
   fflush(stdout);
 }

Main.c

cpp 复制代码
#include "ProgressBar.h"
#include <unistd.h>
double bandwith = 1.2*1000000;

void download(double fileSize)
{
  double current = 0.0;
  printf("download begin\n");
  while(current<=fileSize)
  {
      ProBar2(fileSize,current);
  
      double old = current;
      current += bandwith;
      if(old<fileSize && current>fileSize)
      {
        current = fileSize;
      }
      sleep(1);
  }
  printf("\n");
  printf("download end fileSize:%lf\n",fileSize);
}
  
int main()
{
//  test();
  
//  ProBar();
//  ProBar2(100,56.6);
//  printf("\n");
//  ProBar2(67,66);
//  printf("\n");                                                                                                                                                                                            
//  ProBar2(100,1.2);
//  printf("\n");
    double file = 100.2*1024*1024;
    download(file);

    return 0;
}

执行结果

相关推荐
赖small强13 分钟前
【Linux驱动开发】NOR Flash 技术原理与 Linux 系统应用全解析
linux·驱动开发·nor flash·芯片内执行
00后程序员张17 分钟前
HTTPS Everywhere 时代的抓包挑战,从加密流量解析到底层数据流捕获的全流程方案
网络协议·http·ios·小程序·https·uni-app·iphone
IT运维爱好者1 小时前
【Linux】LVM理论介绍、实战操作
linux·磁盘扩容·lvm
LEEE@FPGA1 小时前
ZYNQ MPSOC linux hello world
linux·运维·服务器
郝学胜-神的一滴1 小时前
Linux定时器编程:深入理解setitimer函数
linux·服务器·开发语言·c++·程序人生
冉佳驹2 小时前
Linux ——— 系统中的用户身份切换、文件权限管理、特殊权限和粘滞位设置
linux·chmod·chown·粘滞位·su 命令·chgrp·umask
Tranquil_ovo2 小时前
【Linux】Makefile 基础
linux
漏洞文库-Web安全2 小时前
Linux逆向学习记录
linux·运维·学习·安全·web安全·网络安全·逆向
无奈笑天下2 小时前
【银河麒麟高级服务器部署本地yum源】
linux·运维·服务器·经验分享
dodod20122 小时前
Ubuntu 24.04 LTS 使用清华大学的 Ubuntu 镜像源以加速下载和更新操作
linux·运维·ubuntu