『Linux升级路』进度条小程序

『Linux升级路』进度条小程序,第1张

『Linux升级路』进度条小程序,第2张

博客主页:小王又困了

系列专栏:Linux

人之为学,不日近则日退

❤️感谢大家点赞收藏⭐评论✍️


目录

一、预备知识

1.1缓冲区

1.2回车和换行

二、倒计时

2.1源代码

2.2注意事项

三、进度条

3.1源代码

3.2实际应用


一、预备知识

1.1缓冲区

我们先观察两段代码的现象:

#include <stdio.h> #include <unistd.h> int main() { printf("Hello Linux!\n"); sleep(3); return 0; }

『Linux升级路』进度条小程序,第3张

 这段代码先执行printf函数,在屏幕上打印出Hellow Linux!,然后执行sleep函数让函数休眠3秒,最后程序结束。

#include <stdio.h> #include <unistd.h> int main() { printf("Hello Linux!"); sleep(3); return 0; }

『Linux升级路』进度条小程序,第4张

 通过上图我们可以看到,当我们去掉 ‘\n’ 对代码进行编译,程序先休眠了3秒,然后在屏幕上打印Hellow Linux!。由于去掉了‘\n’ ,也没有换行。

现象分析:

      看到上面的现象,大家一定会有很大的疑惑。难道程序是先执行了sleep函数,然后再去执行printf函数。这样的猜想是错误的,任何一个C语言程序,没有遇到选择和循环语句,都要严格按照顺序结构去执行,代码都是从上到下依次执行。所以一定是先执行printf函数,再执行sleep函数。那在休眠的3秒里,Hellow Linux!去了哪里呢?代码被保存在了缓冲区中,默认当程序结束的时候才会将缓冲区中的内容刷新出来,带 \n 就是要求把缓冲区的的数据立即刷新到显示器上。

  • 缓冲区是一种用于临时存储数据的区域,通常用于临时保存数据以平衡数据处理速度不匹配的情况。 

1.2回车和换行

     回车和换行是两个与文本文件和文本编辑有关的控制字符,它们在不同的 *** 作系统和编程环境中可能有不同的表现。

回车:将光标移动到当前行的开始(最左侧)

  • 表示为ASCII字符 \r
  • 在打字机时代,回车的原意是将打印头移动到行首,以便在同一行上写入新的文本。
  • 在计算机中,回车通常表示将光标移动到当前行的开头,但不换行到新的一行。

换行:将光标水平方向保持不变,竖直方向向下平移一行。

  • 表示为ASCII字符 \n
  • 在打字机时代,换行的原意是将纸向上移动一行,以便在新的行上写入文本。
  • 在计算机中,换行通常表示将光标移动到下一行的开头。

二、倒计时

2.1源代码

 学习了上面的知识,我们可以写一个倒计时的小程序。

源代码

#include <stdio.h> #include <unistd.h>int main() { int cnt=9; while(cnt>=0) { printf("%d\r",cnt); sleep(1); cnt--; } printf("\n"); return 0; }

效果演示

『Linux升级路』进度条小程序,第5张

如上图,运行我们的程序,却没有想要的倒计时效果,这是因为我们没有刷新缓冲区,执行的结果都存放在缓冲区 。我们要使用fflush接口来刷新缓存区。

『Linux升级路』进度条小程序,第6张

刷新缓冲区

任何一个C程序运行的时候都会默认帮我们打开以下三个流:

  • stdin —— 标准输入流(键盘)
  • stdout —— 标准输出流(显示器)
  • stderr —— 标准错误(显示器)

『Linux升级路』进度条小程序,第7张

这三个流都是FILE*的指针,所以任何一个C程序运行的时候, *** 作系统会帮我们打开以上三个文件。我们只需要看stdout标准输出流,使用fflush接口刷新。

源代码

#include <stdio.h> #include <unistd.h> int main() { int cnt = 9; while(cnt >= 0) { printf("%-2d\r",cnt); fflush(stdout); sleep(1); cnt--; } printf("\n"); return 0; }

 效果演示

『Linux升级路』进度条小程序,第8张

2.2注意事项

格式化控制

     我们需要知道,往显示器上打印整型10,本质上是打印了字符1和字符0。因此打印10,会占用两个字符,而打印0~9只需要一个字符,所以 \r 回车之后只会覆盖一个字符,对第二个字符0始终没有影响,因此我们需要用%-2d来控制,每次打印两个位宽的字符, - 表示将这两个字符左对齐。如果不进行格式化控制,打印出来的结果将是下面这样:

『Linux升级路』进度条小程序,第9张

三、进度条

3.1源代码

     我们实现的进度条进度条除了有进度的推进,还要有百分比提示和转动提示。

processBar.h

#pragma once #include <stdio.h> #include <unistd.h> #include <string.h>#define NUM 103 #define BODY '=' #define HEAD '>' void processbar();

processBar.c

#include "processbar.h"//引用头文件 const char* lable = "|/-\\";//转动提示 void processbar() { char bar[NUM]; int cnt=0; memset(bar,'\0',sizeof(bar)); int len=strlen(lable); bar[cnt]=HEAD; while(cnt<=100) { printf("[%-100s][%d%%][%c]\r",bar,cnt,lable[cnt%len]); fflush(stdout); bar[cnt++]=BODY; if(cnt<100) { bar[cnt]=HEAD; } usleep(100000); } printf("\n"); }

『Linux升级路』进度条小程序,第10张

3.2实际应用

     上面的代码只是演示进度条的原理,但是在实际中,进度条并不是这样用的。以下载东西为例,作为一个进度条,它本身并不知道下载了多少,它只会提供一个接口,在下载东西的时候,调用这个接口,然后将已经下载好的比率作为参数传给进度条模块,它会根据比率打印出对应的进度条样式。

processBar.h

#pragma once #include <stdio.h> #include <unistd.h> #include <string.h> #include <time.h> #include <stdlib.h>#define NUM 103 #define BODY '=' #define HEAD '>' typedef void (*callback_t)(double);void process_flush(double rate);

processBar.c

#include "processbar.h"//引用头文件 const char* lable = "|/-\\";//转动提示char buffer[NUM] = {0}; void process_flush(double rate) { static int cnt = 0; int n = strlen(lable); if(rate <= 1.0) buffer[0] = Head; printf("[\033[4;32;44m%-100s\033[0m][%.1f%%][%c]\r", buffer, rate, lable[cnt%n]); fflush(stdout); buffer[(int)rate] = Body; if((int)rate+1 < 100) buffer[(int)(rate+1)] = Head; if(rate>=100.0) printf("\n"); cnt++; cnt%=n; }

main.c

void download(callback_t cb) // 回调函数的形式 { srand(time(NULL)^1023); int total = FILESIZE; while(total) { usleep(10000); //下载动作 int one = rand()%(1024*1024*10); total -= one; if(total < 0) total = 0; // 当前的进度是多少? int download = FILESIZE - total; double rate = (download*1.0/(FILESIZE))*100.0; // 0 23.4 35.6, 56.6 cb(rate); //process_flush(rate); //printf("download: %f\n", rate); // rate出来了,应该让进度条刷新 } }int main() { download(process_flush); return 0; }


结语: 

     本次的内容到这里就结束啦。希望大家阅读完可以有所收获,同时也感谢各位读者三连支持。文章有问题可以在评论区留言,博主一定认真认真修改,以后写出更好的文章。你们的支持就是博主最大的动力。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/13518073.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-12-23
下一篇 2023-12-27

发表评论

登录后才能评论

评论列表(0条)

保存