• 进度条小程序


    0.前提知识

    1. 缓冲区:在C/C++语言中,会针对标准输出,给用户提供默认的缓冲区,并且根据一定的机制进行刷新(或者用户自己刷新,比如:在输出缓冲区中使用fflush(stdout)就可以直接刷新输出缓冲区)。值得注意的是,这个缓冲区是语言给出的,而不是系统给出的。

    2. 换行和回车:换行和回车是两回事,但是在C语言的换行符\n中,通常都会包含这两个概念(C语言的\n=换行+回车)a.换行,就是将光标挪至垂直位置的下一行b.回车,就是将光标挪至本行行首

    1.简易实现进度条

    另外,如果想要改成Windows下运行,那么只需要修改头文件#include #include ,将代码中的usleep()改为Sleep(),并且调整时间参数#define STIME 1000 * 1000#define STIME 100即可成功在windows环境运行下述代码。

        #include 
        #include 
        #include 
        #define SIZE 101
        #define MAX_RATE 100
        #define STYLE '#'
        #define STIME 1000 * 200//1000 * 1000 = 1秒
        const char* str = "\\|/—";
        void process();
        int main()
        {
            process();
            return 0;
        }
        void process()
        {
            int rate = 0;
            char bar[SIZE] = {0};
            int num = strlen(str);
            while(rate <= MAX_RATE)
            {
                printf("[%-100s][%d%%][%c]\r", bar, rate, str[rate % num]);
                fflush(stdout);
                usleep(STIME);//单位为毫秒
                bar[rate++] = STYLE;
            }
            printf("\n");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    注意:这个代码要注意shell的屏幕尺寸问题,尺寸不够可能显示乱码。

    2.实际开发进度条

    这个版本可以好好学,在过程实践中的确有所应用。

    进度条通常要和某些任务关联的,比如:下载任务。

        #include 
        #include 
        #include 
        #define SIZE 101
        #define MAX_RATE 100
        #define STYLE '#'
        #define STIME 1000 * 200//1000 * 1000 = 1秒
        const char* str = "-\\|/";
        typedef void (*callback_t)(int);
        void process_plus(int rate)//参数是传递了比例,根据比例来打一段进度条
        {
            static char bar[SIZE];
            int num = strlen(str);//旋转光标字符的长度
            static int i = 0;
            if (rate <= MAX_RATE && rate >= 0)
            {
                printf("[%-100s][%3d%%][%c]\r", bar, rate, str[i % num]);//这里换成i是为了让旋转光标能够运作,不受进度条控制,可以让用户职别这个进度条究竟是卡住了还是仍在加载
                fflush(stdout);
                bar[rate] = STYLE;
                i++;
            }
            if (rate == MAX_RATE)//主要是用在下一次别的程序调用这个函数的时候,避免进度条数组中还有#
            {
                memset(bar, '\0', sizeof(bar));
            }//这样程序可以适用与不同的任务
        }
        void download_1(callback_t cb)//第一个下载任务,正常调用
        {
            int rate = 0;
            while (rate <= 100)
            {
                (*cb)(rate++);//回调函数
                usleep(STIME);//单位为毫秒
            }
            printf("\n");
        }
        void download_2(callback_t cb)//第二个加载任务,模拟还在加载的情况,不是进度条程序卡住
        {
            int rate = 0;
            while (rate <= 100)
            {
                (*cb)(rate++);//回调函数
        
                if (rate == 50)
                {
                    rate = 49;
                }
        
                usleep(STIME);//单位为毫秒
            }
            printf("\n");
        }
        int main()
        {
            download_1(process_plus);
            download_2(process_plus);
            return 0;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    在上述代码中,我们新增加了一些功能:

    1. 让进度条随着下载任务返回的行号来实时更新进度条

    2. 让旋转光标的选择和进度条的循环变量hile分离开来,使得旋转光标可以独自旋转,而不依赖于进度条。这样就避免了用户无法分辨进度条程序是卡住了,还是处于加载的状态

    3. 我们模拟了两个下载任务交给main()执行,并且内部发送信号rate给进度条,让用户查看两个下载任务的进度,并且第二个下载任务模拟了上面2.的情形

    3.拓张功能进度条

    我们可以给进度条增添颜色或者加粗、或者替换进度条的字符、亦或者直接使用颜色块来替换进度条字符等等,请发挥您的想象力。

    4.补充Windows下的代码

    虽然我在开头说明了如何修改成Windows下也可以运行的代码,但是我担心您对开头那段话有所误解,因此特意重新修改为在Windows下运行的代码。

        #include 
        #include 
        //#include 
        #include 
        #define SIZE 101
        #define MAX_RATE 100
        #define STYLE '#'
        #define STIME 100//1000 * 1000 = 1秒
        const char* str = "-\\|/";
        typedef void (*callback_t)(int);
        void process_plus(int rate)//参数是传递了比例,根据比例来打一段进度条
        {
            static char bar[SIZE];
            int num = strlen(str);//旋转光标字符的长度
            static int i = 0;
            if (rate <= MAX_RATE && rate >= 0)
            {
                printf("[%-100s][%3d%%][%c]\r", bar, rate, str[i % num]);//这里换成i是为了让旋转光标能够运作,不受进度条控制,可以让用户职别这个进度条究竟是卡住了还是仍在加载
                fflush(stdout);
                bar[rate] = STYLE;
                i++;
            }
            if (rate == MAX_RATE)//主要是用在下一次别的程序调用这个函数的时候,避免进度条数组中还有#
            {
                memset(bar, '\0', sizeof(bar));
            }//这样程序可以适用与不同的任务
        }
        void download_1(callback_t cb)//第一个下载任务,正常调用
        {
            int rate = 0;
            while (rate <= 100)
            {
                (*cb)(rate++);//回调函数
                Sleep(STIME);//单位为毫秒
            }
            printf("\n");
        }
        void download_2(callback_t cb)//第二个加载任务,模拟还在加载的情况,不是进度条程序卡住
        {
            int rate = 0;
            while (rate <= 100)
            {
                (*cb)(rate++);//回调函数
                if (rate == 50)
                {
                    rate = 49;
                }
        
                Sleep(STIME);//单位为毫秒
            }
            printf("\n");
        
        }
        int main()
        {
            download_1(process_plus);
            download_2(process_plus);
            return 0;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
  • 相关阅读:
    JetBrains系列工具,配置PlantUML绘图
    因子分析模型介绍、matlab案例我国上市公司盈利能力与资本结构的实证分析
    【TensorFlow】P1 Google Colab 使用
    JVM系列第二期——双亲委派和类加载器
    《剑指offer第二版》面试题14:剪绳子
    港口视频管理监控系统
    Unity开发者——编辑器技巧
    电脑重装系统c盘如何备份资料
    重学FreeRTOS操作系统之任务篇(一)
    Vue项目中使用element-plus UI库-并对下拉搜索框样式修改-el-select代码封装
  • 原文地址:https://blog.csdn.net/m0_73168361/article/details/133084343