Linux:第一个程序--进度条|区分回车与换行|行缓冲区|进度条代码两个版本|代码测试与优化

上篇文章:Linux:自动化构建-make/Makefile

最终结果预览:

目录

1.区分回车与换行

2.行缓冲区

3.写一个倒计时的程序

4.进度条代码

4.1基石

4.2版本一

加入旋转光标:

另一种显示样式:...

4.3带入场景

4.4版本二

4.4.1需求一

4.4.2优化一

4.4.3需求二

4.4.4需求三

4.4.5优化二

4.5代码测试

优化


1.区分回车与换行

回车与换行并不是同一个概念。

回车是指回到当前行的开始,换行是指新开一行

其中,\r指回车,\n或std::endl;或 \r\n 指回车与换行。

2.行缓冲区

下方代码谁先执行?

下方代码谁先执行?

在C语言中,代码都是从上到下执行的,上述代码在sleep期间,printf一定已经执行完了,只不过数据没有被显示出来,那么在sleep期间,hello字符串在哪里呢?

实际是是被缓存起来了,在程序结束时,会自动刷新。

而对于第一段代码,回车换行会立即刷新到显示器中

那么在第二段代码的前提下,要怎么立即刷新?见下:

3.写一个倒计时的程序

4.进度条代码

4.1基石

先创建三个源文件:

再进入到main.c文件中,包含process.h头文件,并再转换到头文件中:

在头文件中声明方法:

.c文件:

编写makefile:

在阅读 Makefile 时,这三个自动化变量最容易混淆:

符号 含义 示例场景
$@ 目标文件 (Target) main: main.o 中,$@ 就是 main
$^ 所有依赖文件 (All Prerequisites) main: a.o b.o 中,$^ 就是 a.o b.o
$< 第一个依赖文件 (First Prerequisite) main.o: main.c 中,$< 就是 main.c

进行一次调试:

4.2版本一

测试:

测试发现,进度条是回车换行每隔一个%就进行一次,并且等待时间较长,优化:

认识usleep(微秒):

代码:

此时运行结果为:

但是它在输出时,右括号是随着=进行移动的,应该将其大小固定,让=进行移动即可,再优化:

但是此时进度条是倒着打印的,并且进度括号大小没有固定且没有%显示:

原因是在C语言的printf中,%Ns(N为正数)会使字符串右对齐,左侧填充空格。

优化:

加入旋转光标:

原理:| / - \依次出现。

另一种显示样式:...

优化:

4.3带入场景

虽然此时的进度条代码初具雏形,但是并没有实际作用。我们进入main.c文件,假设有一个下载任务,完成下方的简易代码:

4.4版本二

4.4.1需求一

完成一个随着下载进度实时更新的动态进度条。

process.c:

复制代码
    1 #include "process.h"
    2 #include <string.h>
    3 #include <unistd.h>
    4 
    5 #define SIZE 102
    6 #define LABLE '='
    7 
    8 // 进度条版本二
    9 void Process(double total, double current)
   10 {
E> 11     if(current > total)            
   12         return;                                                                                                
   13     // 动态进度条                  
   14     // 1.计算比率
E> 15     double rate = current * 100.0 / total;
   16     char out_bar[SIZE];
   17     memset(out_bar, '\0', sizeof(out_bar));
   18     // 2.填充进度字符
   19     int i = 0;
   20     for( ; i < (int)rate; i++)
   21     {                                                            
   22         out_bar[i] = LABLE;                                      
   23     }                                                            
   24     // 3.刷新进度条                                              
   25     printf("[%-100s][%lf]\r", out_bar, rate);                    
   26     fflush(stdout);                                              
   27 }                                                                
   28                    

main.c:

复制代码
  1 #include "process.h"
  2 #include <unistd.h>
  3 
  4 // 下载
  5 double gtotal = 1024.0; // 目标文件的总大小
  6 double gspeed = 1.0; // 网络速度
  7 void DownLoad(double total)
  8 {
  9     double current = 0.0; // 当前下载了多少
 10     while(current <= total)
 11     {
 12         usleep(5000); // 模拟下载
 13         current += gspeed;
 14 
 15         Process(total, current); // 更新进度条
 16     }
 17 }
 18 int main()
 19 {
 20     // version1
 21     //Process(); // 进度条程序
 22     
 23     DownLoad(gtotal);
 24     return 0;
 25 }                                                    

process.h:

复制代码
  1 #pragma once 
  2 
  3 #include <stdio.h>
  4 
  5 void Process(double tatal, double current);       

查看此时的效果:

4.4.2优化一

进行优化:

4.4.3需求二

在进度条运行过程中,其下载速度也会与网络环境相关,此时添加旋转光标表示仍进行下载的过程:

复制代码
  9 void Process(double total, double current)
 10 {
 11     if(current > total)
 12         return;
 13     // 旋转光标只与process函数有关
 14     static const char *lable = "|/-\\";
 15     int size = strlen(lable);                                                                                            
 16     static int index = 0;                                   
 17                                                             
 18     // 动态进度条                                           
 19                                                             
 20     // 1.计算比率                                           
 21     double rate = current * 100.0 / total;                  
 22     char out_bar[SIZE];                                     
 23     memset(out_bar, '\0', sizeof(out_bar));
 24     
 25     // 2.填充进度字符
 26     int i = 0;
 27     for( ; i < (int)rate; i++)
 28     {
 29         out_bar[i] = LABLE;
 30     }
 31     
 32     // 3.刷新进度条
 33     printf("[%-100s][%5.1lf%%][%c]\r", out_bar, rate, lable[index]);
 34     fflush(stdout);
 35     index++;
 36     index %= size;
 37 
 38     // 4.刷新进度条完成后,换行
 39     if(current >= total)                                       
 40         printf("\r\n");                                        
 41 }   

4.4.4需求三

显示目标内容的容量,当前下载量,网速等数据。

process.c:

复制代码
  1 #include "process.h"
  2 #include <string.h>
  3 #include <unistd.h>
  4 
  5 #define SIZE 102
  6 #define LABLE '='
  7 
  8 // 进度条版本二
  9 void Process(double total, double current, double speed, const char *userinfo)
 10 {
 11     if(current > total)
 12         return;
 13     // 旋转光标只与process函数有关
 14     static const char *lable = "|/-\\";
 15     int size = strlen(lable);
 16     static int index = 0;
 17 
 18     // 动态进度条
 19 
 20     // 1.计算比率
 21     double rate = current * 100.0 / total;
 22     char out_bar[SIZE];
 23     memset(out_bar, '\0', sizeof(out_bar));
 24 
 25     // 2.填充进度字符
 26     int i = 0;
 27     for( ; i < (int)rate; i++)
 28     {
 29         out_bar[i] = LABLE;
 30     }
 31 
 32     // 3.刷新进度条
 33     printf("[%-100s][%5.1lf%%][%c] | %.1lf / %.1lf, speed: %.1lf%s\r", out_bar, rate, lable[index], total, current, speed, userinfo);
 34     fflush(stdout);
 35     index++;
 36     index %= size;                                                                                                                     
 37 
 38     // 4.刷新进度条完成后,换行
 39     if(current >= total)
 40         printf("\r\n");
 41 }

main.c:

复制代码
    1 #include "process.h"
    2 #include <unistd.h>
    3 
    4 // 下载
    5 double gtotal = 1024.0; // 目标文件的总大小
    6 double gspeed = 1.0; // 网络速度
    7 void DownLoad(double total)
    8 {
    9     double current = 0.0; // 当前下载了多少
   10     while(current <= total)
   11     {
   12         usleep(5000); // 模拟下载
   13         current += gspeed;
   14 
E> 15         Process(total, current, gspeed, "MB/s"); // 更新进度条
   16     }
   17 }                                                                                                                                                                                                                                                      
   18 int main()
   19 {
   20     // version1
   21     //Process(); // 进度条程序
   22 
   23     DownLoad(gtotal);
   24     return 0;
   25 }

结果:

4.4.5优化二

网速不是固定不变的,给出随机网速并与进度结合。

复制代码
    1 #include "process.h"
    2 #include <unistd.h>
E>  3 #include <stdlin.h>
    4 #include <time.h>
    5 
    6 // 下载
    7 double gtotal = 1024.0; // 目标文件的总大小
    8 double gspeed = 1.0; // 网络速度
    9 void DownLoad(double total)
   10 {                                                                                                                      
   11     double level[] = {0.01, 0.05, 1.0, 0.5, 1.5, 2.5, 5.5, 10.0, 3.6, 20.0, 30.0, 40.0, 50.0 , 68.9, 89.1, 40.9, 30.1};
   12     int num = sizeof(level)/sizeof(level[0]);
   13 
   14     double current = 0.0; // 当前下载了多少
   15     while(1)
   16     {
   17         usleep(10000); // 模拟下载
E> 18         double speed = level[rand()%num];
   19         current += speed;
   20         if(current >= total)
   21         {
   22             current = total;
   23             Process(total, current, speed, "MB/s"); // 更新进度条
   24             break;
   25         }
   26         else 
   27         {
   28             Process(total, current, speed, "MB/s"); // 更新进度条
   29         }
   30     }
   31 }
   32 int main()
   33 {
   34     // version1
   35     //Process(); // 进度条程序
   36     
   37     DownLoad(gtotal);                                                                                                                      
   38     return 0;
   39 } 

4.5代码测试

复制代码
  1 #include "process.h"  
  2 #include <unistd.h>  
  3 #include <stdlib.h>  
  4 #include <time.h>  
  5   
  6 // 下载  
  7 double gtotal = 1024.0; // 目标文件的总大小  
  8 double gspeed = 1.0; // 网络速度  
  9 void DownLoad(double total)  
 10 {  
 11     double level[] = {0.01, 0.05, 1.0, 0.5, 1.5, 2.5, 5.5, 10.0, 3.6, 20.0, 30.0, 40.0, 50.0 , 68.9, 89.1, 40.9, 30.1};  
 12     int num = sizeof(level)/sizeof(level[0]);  
 13   
 14     double current = 0.0; // 当前下载了多少  
 15     while(current <= total)  
 16     {  
 17         usleep(100000); // 模拟下载  
 18         double speed = level[rand()%num];  
 19         current += speed;  
 20         if(current >= total)  
 21         {  
 22             current = total;  
 23             Process(total, current, speed, "MB/s"); // 更新进度条  
 24             break;  
 25         }  
 26         else  
 27         {  
 28             Process(total, current, speed, "MB/s"); // 更新进度条  
 29         }  
 30     }  
 31 }  
 32 int main()  
 33 {  
 34     // version1                                                                                                     
 35     //Process(); // 进度条程序                                                                                      
 36     srand(time(NULL));                                                                                               
 37     printf("download: \n");                                                                                          
 38     DownLoad(gtotal);                                                                                                
 39     printf("download: \n");                                                                                          
 40     DownLoad(102.0);                                                                                                 
 41     printf("download: \n");                                                                                          
 42     DownLoad(11.9);                                                                                                  
 43     printf("download: \n");                                                                                          
 44     DownLoad(89.0);                                                                                                  
 45     printf("download: \n");                                                                                          
 46     DownLoad(900.0);  
 47                                                                                                                                                                                                                                                          
 48     return 0;                                                                                                         
 49 } 

优化

每一个进度条都是独立的,这里使用回调函数,此外,通过printf函数进行颜色的输出:

process.h:

定义一个返回值为void,名称为flush_t的指针

复制代码
  1 #pragma once 
  2 
  3 #include <stdio.h>
  4 typedef void (*flush_t)(double total, double current, double speed, const char *userinfo);                                                                                                                                                               
  5 void Process(double total, double current, double speed, const char *userinfo);

process.c:

复制代码
  1 #include "process.h"
  2 #include <string.h>
  3 #include <unistd.h>
  4 #include <stdio.h>
  5 
  6 #define SIZE 102
  7 #define LABLE '='
  8 
  9 // 进度条版本二
 10 void Process(double total, double current, double speed, const char *userinfo)
 11 {
 12     if(current > total)
 13         return;                                                                                                                
 14     // 旋转光标只与process函数有关
 15     static const char *lable = "|/-\\";
 16     int size = strlen(lable);
 17     static int index = 0;
 18                                                                                                                                                                         
 19     // 动态进度条
 20     
 21     // 1.计算比率
 22     double rate = current * 100.0 / total;
 23     char out_bar[SIZE];                                                                                                                                                                    
 24     memset(out_bar, '\0', sizeof(out_bar));
 25     
 26     // 2.填充进度字符
 27     int i = 0;
 28     for( ; i < (int)rate; i++)
 29     {
 30         out_bar[i] = LABLE;                                                                                                         
 31     }
 32     
 33     // 3.刷新进度条
 34     // \033[1;32m 绿色 (进度条)
 35     // \033[1;33m 黄色 (百分比)
 36     // \033[1;34m 蓝色 (速度)                                                                                                                        
 37     // \033[0m  重置颜色                                                                                                                                  
 38     printf("[\033[1;32m%-100s\033[0m][\033[1;33m%5.1lf%%\033[0m][%c] | %.1lf / %.1lf, speed: \033[1;34m%.1lf%s\033[0m\r",                                    
 39            out_bar, rate, lable[index], total, current, speed, userinfo);                                                                                                                                                                                
 40     //printf("[%-100s][%5.1lf%%][%c] | %.1lf / %.1lf, speed: %.1lf%s\r", out_bar, rate, lable[index], total, current, speed, userinfo);                     
 41     fflush(stdout);                                                                                                                                       
 42     index++;                                                                                                                                               
 43     index %= size;                                                                                                                                        
 44                                                                                                                                                            
 45     // 4.刷新进度条完成后,换行                                                                                                                           
 46     if(current >= total)                                                                                                                                    
 47         printf("\r\n");                                                                                                        
 48 }                                                                                                                                           
 49   

main.c:

复制代码
  1 #include "process.h"                                                                                                                       
  2 #include <unistd.h>                                                                                                                        
  3 #include <stdlib.h>                                                                                                                        
  4 #include <time.h>                                                                                                                          
  5                                                                                                                                            
  6 // 回调函数                                                                                                                                
  7 double gtotal = 1024.0; // 目标文件的总大小                                                                                                
  8 double gspeed = 1.0; // 网络速度                                                                                                           
  9 void DownLoad(double total, flush_t cb)                                                                                                    
 10 {                                                                                                                                          
 11     double level[] = {0.01, 0.05, 1.0, 0.5, 1.5, 2.5, 5.5, 10.0, 3.6, 20.0, 30.0, 40.0, 50.0 , 68.9, 89.1, 40.9, 30.1};                    
 12     int num = sizeof(level)/sizeof(level[0]);                                                                                              
 13                                                                                                                                            
 14     double current = 0.0; // 当前下载了多少                                                                                                
 15     while(1)                                                                                                                               
 16     {                                                                                                                                      
 17         usleep(100000); // 模拟下载                                                                                                        
 18         double speed = level[rand()%num];                                                                                                  
 19         current += speed;                                                                                                                  
 20         if(current >= total)                                                                                                               
 21         {                                                                                                                                  
 22             current = total;                                                                                                               
 23             cb(total, current, speed, "MB/s"); // 更新进度条                                                                               
 24             break;                                                                                                                         
 25         }                                                                                                                                  
 26         else                                                                                                                               
 27         {                                                                                                                                  
 28             cb(total, current, speed, "MB/s"); // 更新进度条                                                                               
 29         }                                                                                                                                  
 30     }                                                                                                                                      
 31 }                                                                                                                                          
 32 int main()                                                                                                                                 
 33 {                                                                                                                                          
 34     // version1                                                                                                                            
 35     //Process(); // 进度条程序                                                                                                             
 36     srand(time(NULL));                                                                                                                     
 37     printf("download: \n");  
 38     DownLoad(gtotal, Process);  
 39     printf("download: \n");  
 40     DownLoad(102.0, Process);  
 41     printf("download: \n");  
 42     DownLoad(11.9, Process);  
 43     printf("download: \n");  
 44     DownLoad(89.0, Process);  
 45     printf("download: \n");  
 46     DownLoad(900.0, Process);
 47 
 48     return 0;
 49 }      

显示结果:

本章完。

相关推荐
一点晖光2 小时前
jenkins优化记录
运维·jenkins
looking_for__2 小时前
【Linux】Ext系列文件系统
linux
最贪吃的虎3 小时前
Git: rebase vs merge
java·运维·git·后端·mysql
OliverH-yishuihan3 小时前
开发linux项目-在 Windows 上 基于“适用于 Linux 的 Windows 子系统(WSL)”
linux·c++·windows
yBmZlQzJ3 小时前
内网穿透工具通过端口转发实现内外网通信
运维·经验分享·docker·容器·1024程序员节
DeepHacking3 小时前
Overleaf 本地Docker部署
运维·docker·容器
llilian_164 小时前
总线授时卡 CPCI总线授时卡的工作原理及应用场景介绍 CPCI总线校时卡
运维·单片机·其他·自动化
乐迪信息4 小时前
乐迪信息:煤矿皮带区域安全管控:人员违规闯入智能识别
大数据·运维·人工智能·物联网·安全
好好生活_4 小时前
【Docker基础学习】从VM虚拟机到Docker
运维·docker