Linux小程序 —— 进度条

2024-06-04 7913阅读

前言:经过这么多天的学习,想必大家学到了很多Linux知识,今天我们来用Linux来实现我们的第一个小程序 — — 进度条


Linux小程序 —— 进度条 第1张


本篇主要内容将会实现三个版本的进度条:

  • 简单原理版本
  • 实际工程实践版本
  • 拓展版本

    Linux小程序 —— 进度条 第2张

    在实现进度条之前,我们先了解一些之前没提到过的知识,以便我们理解


    进度条

    • 1. 缓冲区的概念
    • 2. \r&&\n
    • 3. 进度条
      • 3.1 版本一
      • 3.2 版本二
      • 3.3 版本三
      • 4. 总结拓展

        1. 缓冲区的概念

        我们先来分析下面几段代码感受一下行缓冲区的存在:

        在Linux当中以下代码的运行结果是什么样的?

        #include 
        #include                        
          
        int main()
        {
            printf("你能看见我嘛\n");
            sleep(2);
            return 0;
        }
        

        这段代码运行结果显而易见:printf函数直接打印内容,然后休眠2秒。

        对于大家可能没有什么难度。那如果我们修改一下代码。

        #include 
        #include                        
          
        int main()
        {
            printf("你能看见我嘛");
            sleep(2);
            return 0;
        }
        

        缓冲区的概念

        通过视频我们发现,我仅仅是将\n删除了,但是却带来了完全不一样的运行结果:先休眠2秒,然后才是printf函数打印内容

        那么为什么会出现这种情况呢? C语言执行代码的逻辑不应该是从上至下执行吗?

        • 按照 C语言执行代码的逻辑printf确实已经运行了,只不过内容没有被显示出来!
        • 内容所在的区域则是在输出缓冲区中!

          C/C++语言,会针对标准输出,给我们提供默认的缓冲区

          fflush函数可以刷新缓冲区,如果我们想立马显现可以用函数刷新fflush(),而\n是一种刷新的策略——行刷新,所以\n也能立马显现!


          2. \r&&\n

          概念:

          • \r: 回车,使光标回到本行首格
          • \n: 换行,使光标移到下一行

            光说可能大家不太理解,我们来实操看看:

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

            回车 \r

            我们可以看到在输出下一个数之前都让光标先回到本行首格。

            但是为什么输出结果和我预想的完全不一样?

            Linux小程序 —— 进度条 第3张

            printf("%-2d\r", cnt--);

            我们以两位字符进行输出,-则是表示靠左对齐,就可以正常输出了!


            3. 进度条

            在进行上面的铺垫之后,我们开始编写我们的第一个小程序。我们将用两个源文件和一个头文件,一个申明,一个调用,一个实现

            test.c:实现

            test.h:申明

            main.c:调用

            // Makefile:
            mytest:test.c main.c
                 gcc -o $@ $^
            .PHONY:clean
            clean:
                 rm -rf mytest 
            

            3.1 版本一

            在版本一中,我们只要简单实现一下基本的功能,得到一个基本框架就足够了。

            // process_v1
            //test.h:申明
            pragma once
            #include 
            #include 
            #include 
              
            // 定义进度条的总长度,因为有'

            3.2 版本二

            '的存在所以设为101 #define SIZE 101 // 定义进度条的当前进度 #define MAX_RATE 100 // 进度条的符号 #define STYLE '#' // 进度条的休眠时间 #define STIME 1000*15 void process_v1(); ............. //test.c:实现 #include "test.h" // 旋转光标 const char *str = "|/-\"; // \:才能表示一个'\' void process_v1() { int rate = 0; //初始化进度条全为'

            3.3 版本三

            ' char bar[SIZE] = {0}; //循环打印 int num = strlen(str); while(rate // 进度条的打印格式 // -100:先取好[]的范围,然后靠左打印。 printf("[%-100s][%d%%][%c]\r", bar, rate, str[rate%num]); // 刷新缓冲区 fflush(stdout); // 休眠时长 usleep(STIME); // 填充符号 bar[rate++] = STYLE; } // 刷新 printf("\n"); } ............. //main.c:调用 #include "test.h int main() { process(); return 0; }

            进度条:版本一

            我们的第一代进度条也就完成了,实现了基本的结构框架!而我们的进度条,肯定不能干自己的,一定是和某种任务关联起来的!


            4. 总结拓展

            我们将循环改成内部维护一个简单的静态缓冲区,每次往缓冲区里面增加内容然后刷新缓冲区内容就可以

            不能一次将进度条打印完毕,否则不能与场景更好的结合

            // process_v2
            //test.h:申明
            #pragma once
             
            #include 
            #include 
            #include 
              
            #define SIZE 101
            #define MAX_RATE 100
            #define STYLE '#'
            #define STIME 1000*15
             
            typedef void(*callback_t)(int); // 回调函数        
            // 这里我们也可以使用函数指针                                       
            void process_v2(int);                                 
            ~                            
            .............
            //main.c:调用
            #include "test.h"
              
            #define TARGET_SIZE 1024*1024 // 模拟下载软件的大小
            #define DSIZE 1024*10 // 模拟下载的速度
              
            //void download()
            //{
            //    int target = TARGET_SIZE; // 软件总体积
            //    int total = 0; // 当前下载的大小
            // 
            //    while(total  
             
             
              
             

            进度条:版本二

            我们也能完成进度条的实现,最后我们在优化一下,变成我们的版本三!。


            因为版本二已经能将进度条完美的呈现了,我们版本三,只是在二的基础上,美化一下,所以只是简单修改一点代码!

            Linux小程序 —— 进度条 第4张

            // test.h
            #define STYLE_DEADER '>'
            #define STYLE_BODY '='
            typedef void (*callback_t)(double);
            .............
            // main.c
            // 我们在下载时,模拟下载中断的状态
            void download(callback_t cb)
            {
                int target = TARGET_SIZE; // 软件总体积
                int total = 0; // 当前下载的大小
             
                while(total 
                    usleep(STIME); // 用休眠时间,模拟下载时间
                    total += DSIZE;
                    double rate = total*100/target; 
                    // 我们让下载进度永远维持在50%左右
                    if(rate  50.0)
                    {
                    	total = target/2;
                    }  
                    cb(rate);  
                }
                printf("\n");
             }
             
            .............
            // test.c
             if(rate = 0)
             {
                // 设置cnt是为了在下载终止时,光标依然能变化
                cnt++;
                cnt = cnt > num ? 0 : cnt;
                // \033[1;47;30m ... \033[0m 则是更改输出时字体和背景颜色
                printf("加载中...\033[1;47;30m%-100s\033[0m][%.1lf%%][%c]\r", bar, rate, str[cnt]);        
                fflush(stdout);
                if(rate  
             
             
              
             

            进度条:版本三

            我们可以发现,我们修改了字体颜色和背景,设置测试了可能遇到的中断情况,光标依旧会变化。当然了进度条还有很多情景,等待着各位开发!


            拓展:

            关于print带颜格式化输出,我在这里推荐一篇博客,有兴趣的可以去了解一下

            print带颜格式化输出


            总结:

            本篇我们简单了解了一下缓冲区,以及换行'\n'与回车'\r'的基本概念,然后由浅入深的介绍了三个版本的进度条,当然了美化方式各位都不一样,都是可以的,我们的Linux第一个小程序就讲到这里

            谢谢大家支持本篇到这里就结束了

            Linux小程序 —— 进度条 第5张


    免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

    目录[+]