初识Linux · 进度条

饭宝  金牌会员 | 2024-9-29 07:11:15 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 843|帖子 843|积分 2529

目录
媒介:
1 缓冲区和回车换行
2 进度条

媒介:

我们现在学习了些许知识,已经足够支持我们写一个非常非常小的项目了,即进度条,相信大家都有过下载游戏,等待游戏更新完成的时候,那么此时就有一个进度条,代表着游戏的更新进度,那么我们今天就来模拟实现这个过程,在此之前,我们需要一些预备知识。

1 缓冲区和回车换行

回车换行?是的,你没有看错,相信不少人对换行有一定的误解,我们在C语言里面使用的\n,代表的就是换行,换行之后,不少人发现光标都移动到下一行的最开始,以是不少人以为换行就是直接到下一行的开始,但是现实上并不是如许的,我们不妨看一下老式的键盘:

可以看到,回车是由一个L外形的,结合我们的语文作文,每次一行写满了,需要写下一行的时候,我们总是先定位到下一行,再回退到最开始,从当前位置定位到下一行的这个动作,就代表的是换行,从当前行的位置回退到最开始的位置的这个动作,就叫做回车,此时肯定有人会想到C语言的\r,代表的正是回车:
  1. printf("%r",...);
复制代码
当\n和\r在一起的时候,\n才是换行,其他时候都是回车换行,今天,我们学习的进度条的项目,就是使用的是\r这个占位符,即光标回退,实验覆盖的操纵。
那么现在再来看看一段代码:
  1.   1 #include <stdio.h>
  2.   2 #include <unistd.h>
  3.   3 int main()
  4.   4 {
  5.   5   printf("Hello Linux!");                                                
  6.   6   sleep(1);
  7.   7   return 0;
  8.   8 }
复制代码
这是在Linux中运行的一段代码,我们在Hello Linux!后面加\n和不加\n是有区别的,当我们没有\n,系统是先休眠一秒钟,然后打印Hello Linux!,但是我们如果在Hello Linux!后面加上了\n,就会先打印Hello Linux!,然后再举行休眠,这个现象不显着,但是可以引出比较巨大的问题。
起首,缓冲区是什么?我们不妨将缓冲区认定为一块内存空间,在C++的学习中我们知道\n是革新缓冲区的标志,以是,当我们没有加\n,printf先将字符串输入到缓冲区,然后等待革新,此时没有革新标志,以是系统实验sleep函数,休眠了1秒,此时程序结束,强制革新缓冲区,以是现象是先休眠再打印,那么有了\n就同理,直接打印再休眠就完事了。
那么为什么强制革新一定是在程序结束了再强制的呢?为什么不能提前强制革新,当然是可以的,我们使用函数fflush即可:

我们可以看到参数是文件指针,那么我们去哪里找呢?
不要忘了,系统是默认打开了三个流,分别是stdin stdout stderror,文件输出流就是stdout,那么为什么是默认打开的?
因为早期的时候,发明编译器的人看到这么多人都有相同的需求,以是就有了后面的默认打开三个流。
那么此期间码就酿成:
  1.   1 #include <stdio.h>
  2.   2 #include <unistd.h>
  3.   3 int main()
  4.   4 {
  5.   5   printf("Hello Linux!");
  6.   6   fflush(stdout);                                                         
  7.   7   sleep(1);
  8.   8   return 0;
  9.   9 }
复制代码
现象就酿成了先打印,然后再sleep,这就是强制革新。
当然了,不用强制革新想要验证缓冲区也很简单,我们只需要在Hello部分加上\n,看打印效果就可以了->打印效果就是先打印Hello然后再打印Linux。
有人就会提问了,为什么非要用\n来表示革新标志呢?
\n革新,简称行革新,我们从缓冲区革新到显示器文件上,要求的应该是少次数多数据量,最初的那批人结合了很多方面,以为行革新是最符合的,既要中和次数,也要考虑数据量的问题,以是选中了\n。

2 进度条

有了以上的基础,我们现在来实现一下进度条。
  1.   1 #pragma once
  2.   2 #include <stdio.h>
  3.   3 #include <string.h>
  4.   4 #include <unistd.h>
  5.   5
  6.   6 #define LENGTH 101
  7.   7 #define style '='
  8.   8 const char* lable = "|/-\";
  9.   9
  10. 10 void processbar()
  11. 11 {
  12. 12   char arr[LENGTH];
  13. 13   memset(arr,'\0',sizeof(arr));
  14. 14   int len = strlen(lable);
  15. 15   int cnt = 0;
  16. 16   while(cnt <= 100)
  17. 17   {
  18. 18     printf("[%-100s][%3d%%][%c]\r",arr,cnt,lable[cnt%len]);
  19. 19     fflush(stdout);  // -> 不加导致卡顿
  20. 20     arr[cnt++] = style;
  21. 21     usleep(20000);
  22. 22
  23. 23   }
  24. 24   printf("\n"); // 不换行会导致命令提示符覆盖进度条                                                                                                                                                           
  25. 25 }
复制代码
自己代码是比较简单的,这里要注意两个点,一个是如果不强制革新,也能到达我们想要的效果,但是是会等usleep休眠完了再打印,以是相对来说是有点卡顿的。
如果最后没有\n,就会导致命令提示符覆盖我们想要的进度条,从而导致覆盖,如:

上面的是正常的,下面的就是没有加,从而导致出现错误。
还有一个小点是要表达%需要加上两个%,就像两个\一样的,防止被转义了。
但是这个进度条版本并不传神,总不可能什么东西都没有,咱们就干巴巴的来个进度条吧?
以是我们实现第二个版本,加点修饰什么的:
  1. typedef void(*callback_t)(double,double);                                                            
  2. void processbar(double total,double current)                                                        
  3. {                                                                                                   
  4.    char arr[LENGTH];                                                                                 
  5.    memset(arr,'\0',sizeof(arr));                                                                     
  6.    double rate = (current * 100.0) / total;                                                           
  7.    int loop_rate = (int)rate;                                                                        
  8.    int len = strlen(lable);                                                                           
  9.    int cnt = 0;                                                                                       
  10.    while(cnt <= loop_rate)                                                                           
  11.    arr[cnt++] = style;                                                                              
  12.    printf("[%-100s][%3.1lf%%][%c]\r",arr,rate,lable[cnt%len]);                                       
  13.    fflush(stdout);                                                                                   }                                                                                                   
复制代码
在进度条的头文件里面,我们稍加修饰,在主函数里面也一样:
  1.   3 void Down_load(double filesize,callback_t cb)                                                                                                         
  2.   4 {                                                                                                         
  3.   5   double current = 0,bandtwidth = 1024*1024;                                                                                                                                                                  
  4.   6   printf("Download begin...\n");                                                                                                         
  5.   7   while(current <= filesize)                                                                                                         
  6.   8   {                                                                                                         
  7.   9     cb(filesize,current);                                                                                                         
  8. 10     usleep(20000);                                                                                                         
  9. 11     current += bandtwidth;                                                                                                         
  10. 12   }                                                                                                         
  11. 13   printf("Download done...\n");                                                                                                         
  12. 14 }
复制代码
此时进度条的最简易版本就出来了。

感谢阅读!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

饭宝

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表