Linux | 进度条 | Linux简单小程序 | 超级简单 | 这一篇就够了

进度条—实例示范

在学习了基本的Linux指令,Linux上vim编译器等等之后,我们就来学习写代码喽~

今天就给大家详细讲解一下进度条的编写,需要的效果如下图:

进度条—必备知识

回车和换行

在我们学习编程语言中,经常使用的 [ \n ] ,是什么意思呢?

  • C 语言中有很多字符,而字符大体分为两类:可显字符、控制字符。
  • 控制字符不可显示,例如 \r 和 \n 就是控制字符。

而在我们平时打字时,一行写满了需要换行,其实只根据字面思想来看,换行就是单纯地换行,也就是使光标跳到下一行就是换行。但是这也仅仅只是换行,如下图光标是在行尾的下面,也就是第一行的行尾,所以这是符合我们习惯的。

我们通常的习惯是,在第二段的最左端开始新一行的内容,而要是光标从上一行的行尾,跳到下一行的最左端就应该是两个动作的:换行和回车。

回车就是回到本行的文本行的开头。

所以在编程语言中, [ \n ] 其实两个动作:

  • [ \n ] :换行 + 回车

那么什么是回车呢?

  • [ \r ] :换行 

缓冲区

必备知识点

sleep
  • sleep:Linux 下的休眠函数,单位是秒。头文件为 #include <unistd.h>。

sleep的效果样式,如下图,系统就会休眠3秒。

如下例子,当我们将 [ \n ] 删掉,运行程序我们发现下面会出现:

光标一直闪烁,但是一直都不打印,这似乎是在等待sleep3秒结束之后,因为没有 [ \n ] ,所以也一直等到程序结束时,与shell命令行提示一起打印出来,shell提示符紧跟字符串后面显示。

这反而像是sleep函数先起作用,然后printf函数再从光标处开始打印。

#include <stdio.h>
#include <unistd.h>
int main()
{
    //printf("hello world,hello world...\n");     
    printf("hello world,hello world...");                                                                                  
    sleep(3);
 
    return 0;
}

加上 [ \n ] 与 不加 [ \n ] 的区别似乎就是:

  • 加上 [ \n ]:printf执行结束,字符串直接显示出来,然后sleep;
  • 不加 [ \n ]:字符串没有打印出来,先sleep之后,字符串才打印出来。

那么在第二种代码情况下,printf与sleep函数哪个先运行呢?

  • 当然是printf先显示出来;
  • 因为这串字符串并没有换行符,所以打印的字符串必须与命令行的下一行为同一行;
  • C语言执行代码时,永远都是从上往下执行的;
  • 在sleep期间,printf的字符串已经打印出来了,只是这串字符串没有显示出来罢了;
  • 在sleep之后,消息才显示出来。

那么既然printf的字符串已经打印出来了,只是没有显示出来,在sleep期间,字符串是在哪里的呢?

  • 缓冲区

缓冲区理解

缓冲区,可以理解为一块内存空间。

当进行printf打印字符串的时候,字符串被拷贝到了缓冲区,sleep之后,字符串被从缓冲区刷新到显示器,这样就在屏幕上打印出来了字符串了。

一般在程序结束时候或者等到缓冲区满的时候,自动冲刷缓冲区。

缓冲区默认是行刷新的,遇到 [ \n ] 就刷新。

刷缓冲区方式

那么如果不想等到程序结束的时候,直接冲刷缓冲区,如何做呢?

  • [ \n ];
  • 缓冲区已满;
  • 强制刷新。

在打印字符串的后面加上一行强制冲刷缓冲区的代码:

  • fflush(stdout) :刷新缓冲区。
fflush(stdout);                                                                                   
#include <stdio.h>
#include <unistd.h>
int main()
{
    //printf("hello world,hello world...\n");     
    printf("hello world,hello world...");
    fflush(stdout);//强制冲刷缓冲区                                                                              
    sleep(3);
 
    return 0;
}

实现倒计时 

光标和显示器匹配,光标在哪里,显示器打印的时候就从哪里开始打印 。

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

int main()
{
    int cnt=10;
    while(cnt>=0)
    {
        printf("倒计时:%2d\r",cnt);
        sleep(1);
        fflush(stdout);
        cnt--;

    }
    printf("\n");                    
    return 0;
}

 

进度条代码

“ProgressBar.h”头文件

#include "ProgressBar.h"
#include <unistd.h>
//download
double bandwidth=1024*1024*1.0;
void download(double filesize,callback_t cd)
{
    double current=0.0;
    double bandwidth=1024*1024*1.0;

    printf("download done,current:%lf\n",current);
    while(current<=filesize)
    {
        cd(filesize,current);
        //从网络中获取数据
        current+=bandwidth;
        usleep(10000);
    
    }
    printf("\ndownload done,filesize:%lf\n",filesize);
}

int main()
{
    //ForTest();
    //ProgBar(100.0,10.34);
    //ProgBar(100.0,20.34);
    //ProgBar(100.0,99.98);
    //ProgBar(100.0,56.74);
    //ProgBar(100.0,69.98);
    download(100*1024*1024,ProgBar);
    download(50*1024*1024,ProgBar);
    download(800*1024*1024,ProgBar);
    download(890*1024*1024,ProgBar);
    download(67*1024*1024,ProgBar);
    download(10*1024*1024,ProgBar);
    return 0;
}                                                                

“ProgressBar.c”函数文件

#include "ProgressBar.h"
#include <string.h>
#include <unistd.h>

//version 1
//#define Length 101
//#define Style '#'
//const char* lable="|/-\\";
//void ProgBar()
//{
//   char bar[Length];
//   memset(bar,'\0',sizeof(bar));
//   int len =strlen(lable);

//   int cnt=0;
//   while(cnt<=100)
//  {
//       printf("[%-100s][%3d%%][%c]\r",bar,cnt,lable[cnt%len]);
//       fflush(stdout);
//       bar[cnt++]=Style;
//       usleep(100000);
//  }
//   printf("\n");
//}

#define Length 101
#define Style '#'
const char* lable="|/-\\";
//version 2
void ProgBar(double total,double current)
{
    char bar[Length];
    memset(bar,'\0',sizeof(bar));
    int len =strlen(lable);
    int cnt=0;
    double rate=((current*100.0)/total);
    int loop_count=(int)rate;
    while(cnt<=loop_count)
    {
        bar[cnt++]=Style;
    }
        printf("[%-100s][%.1lf%%][%c]\r",bar,rate,lable[cnt%len]);
        fflush(stdout);
}

“Test.c”测试文件

#include "ProgressBar.h"
#include <unistd.h>
//download
double bandwidth=1024*1024*1.0;
void download(double filesize,callback_t cd)
{
    double current=0.0;
    double bandwidth=1024*1024*1.0;

    printf("download done,current:%lf\n",current);
    while(current<=filesize)
    {
        cd(filesize,current);
        //从网络中获取数据
        current+=bandwidth;
        usleep(10000);
    
    }
    printf("\ndownload done,filesize:%lf\n",filesize);
}

int main()
{
    //ForTest();
    //ProgBar(100.0,10.34);
    //ProgBar(100.0,20.34);
    //ProgBar(100.0,99.98);
    //ProgBar(100.0,56.74);
    //ProgBar(100.0,69.98);
    download(100*1024*1024,ProgBar);
    download(50*1024*1024,ProgBar);
    download(800*1024*1024,ProgBar);
    download(890*1024*1024,ProgBar);
    download(67*1024*1024,ProgBar);
    download(10*1024*1024,ProgBar);
    return 0;
}                                                                

  • 33
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安心学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值