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
相关推荐
somi7几秒前
ARM-驱动-03 Linux 字符设备驱动开发
linux·arm开发·驱动开发·自用
CDN3603 分钟前
高防服务器带宽跑满、业务掉线?流量限制与清洗优化
运维·服务器
似水এ᭄往昔4 分钟前
【Linux】--程序地址空间
linux·运维·服务器
云飞云共享云桌面10 分钟前
8-10位研发3D(sw、ug、creo)画图如何共享一台工作站?
运维·服务器·网络·数据库·3d·电脑
Turboex邮件分享11 分钟前
邮件系统中的抗拒绝服务(DDoS)攻击防护
运维·网络·安全·ddos·软件需求
成为你的宁宁14 分钟前
【docker镜像加速器配置】
运维·docker·容器
DeeplyMind23 分钟前
Linux 内核补丁提交(Upstream)完整指南
linux·upstream
三道渊26 分钟前
Linux进程通信与信号处理全解析
linux·服务器·网络
AI_Claude_code28 分钟前
ZLibrary访问困境方案六:自建RSS/Calibre内容同步服务器的完整指南
运维·服务器·网络·爬虫·python·tcp/ip·http
Java后端的Ai之路28 分钟前
sudo 命令详解:Linux 权限管理的“万能钥匙“
linux·运维·服务器·sudo