进度条制作--Linux知识的小应用

发布于:2025-07-29 ⋅ 阅读:(15) ⋅ 点赞:(0)

目录

一:回车与换行

二:缓冲区

三:显示器类型概念

四:进度条制作

4.1倒计时程序

​4.2进度条制作


一:回车与换行

回车:回到这一行的起点   \r

换行:换到下一行与该行相同的位置  \b

先回车再换行,可以达到在新的一行从头开始


二:缓冲区

\n:可以刷新缓冲区,把缓冲区的内容输出

根据上面的代码和运行结果可以看出,如果代码最后有\n,结果是先打印结果,然后睡眠2秒

如果代码最后没有\n,结果是先睡眠2秒,然后在打印结果,且最后没有换行

是\n,改变了代码执行顺序吗?

不,不管最后有没有\n,代码执行程序都是从上往下,先执行printf,再执行sleep,但是不带\n的现象感觉是先执行sleep,然后执行printf呢?如果都是先执行printf,那么不带\n的情况下,执行完的printf,原本该在显示器打印出来的字符串在哪里呢?----缓冲区

一种刷新是程序执行完,退出的时候,将缓冲区的内容一次性刷新到显示器中,这就是不带\n的时候,为什么先看到sleep的现象,再看到打印的字符串

另外一种就是\n,\n表示一种强制刷新,是行刷新,遇到\n会将缓冲区一行的内容刷新到显示器中

还有一种刷新方式就是fflush刷新

 

使用fflush就可以达成刷新缓冲区,但是不换行 

三:显示器类型概念

我们在定义的时候,a是int类型的,预料中打印应该是整数1234,结果也和预期是一样的
但是打印的是整数1234,还是1 2 3 4这四个字符,组合起来让我们以为是整数呢?

结论是:显示器没有类型概念,它在打印的时候是一个一个字符打印的

那为什么它的显示结果还和我们预想的一样呢?

四:进度条制作

4.1倒计时程序

根据上面的知识,我们可以实现一个小的倒计时程序,即在同一个行实现数字变换,从9->0

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

 如果使用上述代码执行,10->0呢?

此时会有一个新的问题,10在显示器来说是两个字符,但是9到0只是一个字符,此时就会出现,9到0,只会更换一个字符,另一个字符保持不变,如果要改变这种情况,就要把0~9变成两个字符

 4.2进度条制作

在知道倒计时程序的使用之后,可以进一步制作进度条,首先我们要明确进度条都需要哪些要素?

1.有一个进度框,框里面是进度条的移动,一般是一次性大小就固定不动

2.进度条随着进度的执行,在进度框里面向后移动

3.会显示当前进度的数字

4.有的时候进度数字后面还有一个交替变换的加载符号

根据上面的要素,以及前面的知识,可以写一个进度条代码:

process.h

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

void Process();

process.c

#include "process.h"

#define NUM 101
#define STYLE '='

//效果[====>                           ]  [ ] [ ],最后>会消失
void Process()
{
    const char* lable = "|/-\\";
    int len = strlen(lable);

    char bar[NUM];
    memset(bar,'\0',sizeof(bar));

    int cnt = 0;
    while(cnt <= 100)
    {
        printf("[%-100s][%d%%][%c]\r",bar,cnt,lable[cnt%len]);//进度条主体
        fflush(stdout);//刷新缓冲区,显示到显示器中
        bar[cnt] = STYLE;
        cnt++;

        //处理最后一个字符
        if(cnt == NUM)
        {
            bar[cnt-1] = '\0';
            printf("[%-100s][%d%%][%c]\r",bar,cnt-1,lable[(cnt-1)%len]);//进度条主体
            break;
        }

        bar[cnt] = '>';
        usleep(50000);//unsleep单位是微秒,sleep单位是秒
    }
}

main.c 

#include<stdio.h>
#include "process.h"

int main()
{
    Process();
    
    return 0;
}

Makefile:

process : process.c main.c
	gcc -std=c99 -o $@ $^

.PHONY : clean
clean:
	rm -rf process

运行结果:

4.3进度条的场景应用

进度条一般用在下载量,动态刷新...

下面模拟一下进度条在下载量的实际应用:

process.h

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

void FlushProcess();

process.c

#include "process.h"

#define NUM 101
#define SPACE ' '
#define STYLE '='
#define POINT '.'
const int pnum = 3;


void FlushProcess(double total, double current)
{
    //1.更新当前的百分比
    double rate = (current / total)*100;

    //2.更新当前的进度条
    char bar[NUM];//每1%更新一个进度条
    memset(bar,'\0',sizeof(bar));

    for(int i = 0; i < (int)rate;i++)
    {
        bar[i] = STYLE;
    }

    //3.更新旋转光标,...的数量
    //为什么要加上旋转光标?
    //如果进度条缓慢,每次进入函数,取整之后进度条没有变化,此时可以通过旋转光标有无变化来判断程序是否在正常运行
    static int num = 0;
    num++;
    num %= pnum;
    char points[pnum+1];
    for(int i = 0; i < pnum;i++)
    {
        if(i < num)
            points[i] = POINT;
        else
            points[i] = SPACE;

    }

    //4.打印进度条
    printf("[%-100s][%.1lf%%]%s\r",bar,rate,points);
    fflush(stdout);
}

 main.c

#include<stdio.h>
#include "process.h"
#include<time.h>
#include <stdlib.h>



typedef void(*flush_t) (double total,double current); //函数指针

const int base = 20;//单词下载量的基础值
double total = 2048.0;//需要下载的量
double once = 0.1;//速度

void download(flush_t f)
{
    double current = 0.0;
    while(current < total)
    {
        //模拟下载行为
        int r = rand()%base+1;
        double speed = r * once;
        current += speed;
        if(current > total) current = total;
        usleep(10000);

        //更新本次下载量
        f(total,current);
    }
    printf("\n");
}

int main()
{
    srand(time(NULL));
    download(FlushProcess);
    download(FlushProcess);
    download(FlushProcess);
    download(FlushProcess);

    return 0;
}

Makefile

process : process.c main.c
	gcc -std=c99 -o $@ $^

.PHONY : clean
clean:
	rm -rf process

 运行结果:

 


网站公告

今日签到

点亮在社区的每一天
去签到