Linux小程序——进度条

预备知识

缓冲区

先看下面两段代码

c 复制代码
int main()
{
    printf("hello world\n");
    sleep(2);
    return 0;
}
c 复制代码
int main()
{
    printf("hello world");
    sleep(2);
    return 0;
}

第一段代码会直接显示hello world,然后等待两秒,程序结束。第二段代码,则会先等待两秒,在显示hello world。由此可以得出printf函数已经跑完,输出的字符串一定是被保存了起来,在退出的时候才能刷新出来。输出的字符串被保存的地方就是对应的缓冲区

回车与换行

换行:指的是光标从一行换到另一行的对应位置

回车:指的是光标回到这一行的最前面

回车对应的转义字符为\r

下面先来练习写一个倒计时的代码

c 复制代码
#include <stdio.h>
#include <unistd.h>
int main()
{
    int cnt=10;
    while(cnt)
    {
        printf("%-2d\r", cnt--);
        fflush(stdout);
        sleep(1);
    }
    return 0;
}

fflush函数会直接把缓冲区里的内容刷新到屏幕上


所用到的函数

c 复制代码
#include <unistd.h>
unsigned int sleep(unsigned int seconds);//当程序在运行时,执行到sleep时休眠上seconds秒
c 复制代码
#include <stdio.h>
int fflush(FILE*stream);//强制刷新一个流,(可以将缓冲区里的内容强制刷新到屏幕上)
c 复制代码
#include <unistd.h>
int usleep(useconds_t usec);//休眠的时间单位是微秒

项目源码

processbar.h

c 复制代码
#pragma once 

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

#define NUM 103
#define Body '='
#define Head '>'

typedef void (*callback_t)(double);

//version 1

void process();

void process_flush(double rate);

processbar.c

c 复制代码
#include "processbar.h"

const char* lable="|/-\\";

void process()
{
    char buffer[NUM];
    memset(buffer, '\0',sizeof(buffer));
    int cnt = 0;
    int n=strlen(lable);
    buffer[0]=Head;
    while(cnt <= 100)
    {
        printf("[%-100s][%-3d%%][%c]\r", buffer, cnt, lable[cnt%n]);
        fflush(stdout);
        buffer[cnt++] = Body;
        if(cnt<100)
            buffer[cnt] = Head;
        usleep(10000);
    }
    printf("\n");
}

char buffer[NUM] = { 0 };
void process_flush(double rate)
{
    static int cnt = 0;
    int n = strlen(lable);
    if(rate <= 1.0)
        buffer[0]=Head;
    printf("[%-100s][%-5.1lf%%][%c]\r", buffer, rate, lable[cnt%n]);
    fflush(stdout);
    buffer[(int)rate] = Body;
    if(rate<99)
    buffer[(int)rate+1] = Head;
    if(rate >= 100.0)
        printf("\n");
    cnt++;
    cnt%=n;
}

main.c

c 复制代码
#include "processbar.h"
#include <time.h>
#include <stdlib.h>

#define FILESIZE 1024*1024*1024

// 模拟下载任务
void download(callback_t cb) // 回调函数的形式
{
    srand(time(NULL));
    int total = FILESIZE;
    while(total)
    {
        usleep(5000);
        int one = rand()%(1024*1024*5);
        total -= one;
        if(total < 0)
            total = 0;

        // 当前的进度
        int download = FILESIZE - total;
        double rate = (download*1.0/(FILESIZE))*100.0;
        cb(rate);
    }
}

int main()
{
    //process();
    download(process_flush);
    return 0;
}

makefile

makefile 复制代码
processbar:main.o processbar.o
	gcc -o $@ $^
main.o:main.c
	gcc -c main.c
processbar.o:processbar.c
	gcc -c processbar.c
	
.PHONY:clean
clean:
	rm -rf main.o processbar.o processbar
相关推荐
ALex_zry1 小时前
Docker Compose运维技术实战分享:从安装到架构解析
运维·docker·架构
t198751285 小时前
在Ubuntu 22.04系统上安装libimobiledevice
linux·运维·ubuntu
skywalk81635 小时前
linux安装Code Server 以便Comate IDE和CodeBuddy等都可以远程连上来
linux·运维·服务器·vscode·comate
@游子5 小时前
内网渗透笔记-Day5
运维·服务器
晚风吹人醒.6 小时前
缓存中间件Redis安装及功能演示、企业案例
linux·数据库·redis·ubuntu·缓存·中间件
记得记得就1516 小时前
【Nginx 性能优化与防盗链】
运维·nginx·性能优化
Yawesh_best6 小时前
告别系统壁垒!WSL+cpolar 让跨平台开发效率翻倍
运维·服务器·数据库·笔记·web安全
roman_日积跬步-终至千里6 小时前
【Docker】Docker Stop 后到底发生了什么?——从信号机制到优雅停机
运维·docker·容器
喵手6 小时前
云端智变:基于 DevUI 与 MateChat 打造下一代云原生智能运维中台实战教学!
运维·云原生·devui·matechat
Hard but lovely6 小时前
linux: pthread库的使用和理解
linux