Linux

关注公众号 jb51net

关闭
首页 > 网站技巧 > 服务器 > Linux > Linux命令行进度条

Linux在命令行环境中实现进度条的原理解析

作者:倔强的石头_

在Linux命令行环境中,进度条是一种直观展示任务执行进度的重要方式,本文将通过一个简单的C语言进度条程序,深入解析其实现原理和优化过程,希望对大家有所帮助

引言

在Linux命令行环境中,进度条是一种直观展示任务执行进度的重要方式。

本文将通过一个简单的C语言进度条程序,深入解析其实现原理和优化过程

进度条基础原理

进度条的核心功能是将一个耗时操作的完成情况以可视化的方式展示给用户。在命令行环境中,我们通常使用字符界面来实现这一功能。

一个基本的进度条需要包含以下元素:

基础版进度条实现

我们先来看第一个版本的进度条实现:

// process.h
#pragma once
#include <stdio.h>
//v1
void process();
// process.c (v1部分)
#include "process.h"
#include <string.h>
#include <unistd.h>

#define SIZE 101
#define STYLE '='

// v1: 展示进度条基本功能
void process()
{
    int rate = 0;
    char buffer[SIZE];
    memset(buffer, 0, sizeof(buffer));
    const char *lable = "|/-\\";
    int len = strlen(lable);

    while(rate <= 100)
    {
        printf("[%-100s][%d%%][%c]\r", buffer, rate, lable[rate%len]);
        fflush(stdout);
        buffer[rate] = STYLE;
        rate++;
        usleep(10000);
    }

    printf("\n");
}

这个基础版本的进度条实现了以下功能:

关键点解析:

\r的作用:将光标移动到行首,实现覆盖刷新

输出缓冲区刷新:确保每次输出立即显示

旋转动画:通过数组循环选择不同字符实现

解耦与通用化设计

基础版本虽然实现了进度条的基本功能,但存在明显的局限性:

为了解决这些问题,我们来看第二个版本的实现:

// process.h (v2部分)
//v2
void FlushProcess(const char*, double total, double current);
// process.c (v2部分)
#include "process.h"
#include <string.h>
#include <unistd.h>

#define SIZE 101
#define STYLE '='

//v2: 根据进度,动态刷新一次进度条
void FlushProcess(const char *tips, double total, double current)
{
    const char *lable = "|/-\\";
    int len = strlen(lable);
    static int index = 0;
    char buffer[SIZE];
    memset(buffer, 0, sizeof(buffer));

    double rate = current*100.0/total;
    int num = (int)rate;

    int i = 0;
    for(; i < num; i++)
        buffer[i] = STYLE;

    printf("%s...[%-100s][%.1lf%%][%c]\r", tips, buffer, rate, lable[index++]);
    fflush(stdout);
    index %= len;

    if(num >= 100)printf("\n");
}

这个版本的主要改进在于:

解耦后的进度条函数具有更好的通用性,可以应用于各种不同的场景。

回调机制与业务集成

为了将进度条应用到实际业务中,我们采用回调函数机制:

// main.c
#include "process.h"
#include <unistd.h>
#include <time.h>
#include <stdlib.h>

//函数指针类型
typedef void (*call_t)(const char*,double,double);

double total = 1024.0;
double speed[] = {1.0, 0.5, 0.3, 0.02, 0.1, 0.01};

//回调函数
void download(int total, call_t cb)
{
    srand(time(NULL));
    double current = 0.0;
    while(current <= total)
    {
        cb("下载中", total, current); // 进行回调
        if(current>=total) break;
        // 下载代码
        int random = rand()%6;
        usleep(5000);
        current += speed[random];
        if(current>=total) current = total;
    }
}

void uploadload(int total, call_t cb)
{
    srand(time(NULL));
    double current = 0.0;
    while(current <= total)
    {
        cb("上传中", total, current); // 进行回调
        if(current>=total) break;
        // 下载代码
        int random = rand()%6;
        usleep(5000);
        current += speed[random];
        if(current>=total) current = total;
    }
}

int main()
{
    download(1024.0, FlushProcess);
    printf("download 1024.0MB done\n");
    download(512.0, FlushProcess);
    printf("download 512.0MB done\n");
    download(256.0,FlushProcess);
    printf("download 256.0MB done\n");
    download(128.0,FlushProcess);
    printf("download 128.0MB done\n");
    download(64.0,FlushProcess);
    printf("download 64.0MB done\n");
    uploadload(500.0, FlushProcess);
    return 0;
}

这个设计的关键点在于:

进阶优化思路

基于现有代码,我们可以进一步优化:

下面是一个增加颜色支持的示例代码:

// 添加颜色支持的进度条函数
void FlushProcessColor(const char *tips, double total, double current)
{
    const char *lable = "|/-\\";
    int len = strlen(lable);
    static int index = 0;
    char buffer[SIZE];
    memset(buffer, 0, sizeof(buffer));

    double rate = current*100.0/total;
    int num = (int)rate;

    int i = 0;
    for(; i < num; i++)
        buffer[i] = STYLE;

    // 根据进度设置不同颜色
    const char *color = "\033[0;32m"; // 默认绿色
    if(rate < 30.0) color = "\033[0;31m"; // 红色
    else if(rate < 70.0) color = "\033[0;33m"; // 黄色
    
    printf("%s%s...[%-100s][%.1lf%%][%c]\033[0m\r", color, tips, buffer, rate, lable[index++]);
    fflush(stdout);
    index %= len;

    if(num >= 100)printf("\n");
}

总结

通过这个简单的进度条程序,我们学习了:

进度条虽然看似简单,但涉及到了界面设计、算法优化和系统交互等多个方面的知识。在实际开发中,我们可以根据需求进一步扩展这个基础框架,实现更复杂、更美观的进度展示功能。

到此这篇关于Linux在命令行环境中实现进度条的原理解析的文章就介绍到这了,更多相关Linux命令行进度条内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文