Linux | 相关知识点 | 可以通过点击 | 以下链接进行学习 | 一起加油! |
---|---|---|---|---|
初识指令 | 指令进阶 | 权限管理 | yum包管理与vim编辑器 | GCC/G++编译器 |
make与Makefile自动化构建 | GDB调试器与Git版本控制工具 |
文章目录
- 一、知识铺垫
-
- [1.1 回车与换行概念](#1.1 回车与换行概念)
- [1.2 缓冲区](#1.2 缓冲区)
- 二、实现简单倒计时
- 三、进度条
-
- [3.1 Verrsion1:进度条实现](#3.1 Verrsion1:进度条实现)
- [3.2 下载场景](#3.2 下载场景)
-
- [3.2.1 Main.c](#3.2.1 Main.c)
- [3.2.2 Version2:进度条实现](#3.2.2 Version2:进度条实现)
在Linux编程的学习过程中,制作一个进度条小程序是入门的好选择。本教程将从零开始,带你轻松实现第一个Linux进度条,感受编程的乐趣与成就
一、知识铺垫
1.1 回车与换行概念
- 【回车】:回到该行首位置
- 【换行】:跳转到下一行
在编程中,转义字符\r
表示回车符,将光标移动到行首,而\n
表示换行符,将光标移动到下一行首。其中\n
完成了两种行为:换行和回车。
1.2 缓冲区
在计算机中,缓冲区是一个临时存储区域,用于存放数据以便于处理。
在显示器上下文中,缓冲区主要指的是显存(视频内存),用于存储即将显示的图像或文本内容。这样,系统可以先将所有待显示的数据加载到缓冲区,然后一次性地将其刷新到屏幕上,以提高显示效率和流畅度。
二、实现简单倒计时
c
#include <stdio.h>
#include <unistd.h>
int main()
{
int cnt = 9;
while (cnt >= 0)
{
printf("%d\r", cnt);
cnt--;
sleep(1);
}
return 0;
}
实现一个简单动态效果的倒计时,动态效果就是在同一个位置不断数据进行刷新 ,达到动态效果。代码转义字符部分,不采用\n
,而是\r
。由于\n
会换行,无法达到同一位置不断数据进行刷新的目的,而\r
会在本行返回行首。
【数据没有显示】
由于存在 \r
转义字符,虽然数据会被打印出来,但光标会被移回到行的最左侧。这意味着后续打印的内容将覆盖当前行的开头部分。(打印-光标回到行首-打印覆盖)
【fflush强制刷新】
如果使用\r
时数据没有显示,可能是因为终端的刷新机制。有时输出缓冲区没有立即刷新。你可以在每次打印后调用fflush(stdout);
来强制刷新输出缓冲区。
cpp
#include <stdio.h>
#include <unistd.h>
int main()
{
int cnt = 10;
while (cnt >= 0)
{
printf("%2d\r", cnt);
fflush(stdout); // 刷新输出缓冲区
cnt--;
sleep(1);
}
printf("\n倒计时结束!\n");
return 0;
}
【数据没有完全被覆盖 】:由于字符10
到字符0~9
中,会出来一个字符没有被覆盖,这里可以通过在d前面填加数据,确保数据被覆盖完全。
三、进度条
设计进度条初步想法:有特殊字符表示进度和目前进度占比及其旋转光标。
【在makefile文件 】
在makefile文件
中,头文件不用出现,头文件本身就在我的当前目前下,目录下进行编译,你的原文件已经证明了,#include
这个源文件"是在当前目录下的,对此我们makefile文件
不需要存在。@^
就是代表整个依赖文件,中间需要空格进行隔开。
3.1 Verrsion1:进度条实现
"Version1是用于搭建大体轮廓",并不是完善好的版本。
c
#include"Process bar.h"
#define Length 101//设计缓冲区长度,其中为'\0'多开一块空间
#define Style '#'//设计进度条状态,显示特殊字符
const char* lable = "|/-\\";
//version1
void ProcessBar()
{
char bar[Length];//定义缓冲区
memset(bar, '\0', sizeof(bar));//设置缓冲区初始数值,清空缓冲区数据操作
int len = strlen(lable);
int cnt = 0;
while (cnt <= 100)
{
printf("[%100s][%d%%][%c]\r", bar,cnt,lable[cnt%len]);
fflush(stdout);
bar[cnt++] = Style;
usleep(10000);
}
printf("\n");
}
[\r、fflush部分 ]:前期工作,在代码部分进行注释说明。这里主要是针对循环体进行说明。首先是
\r
和fflush
使用上,该点倒计时有过分享,就是需要使用fflush刷新缓冲区数据,提前将数据进行打印,否则由于\r光标回退,新内容进行覆盖,出现无法观察到数据出现情况。
[usleep函数部分]
- usleep函数,同sleep函数效果是一致的。由于使用sleep导致程序休眠时间过长,进度条特殊字符缓慢。
usleep在休眠的时间单位叫做 :
micro second
微秒时间单位转换 :
1秒等于1000毫秒
1毫秒等于1000微秒
[printf输出格式部分][%-100s ]:如果是单纯%s,会导致右括号跟特殊字符增多,而跟着跑。这里选择预留空间,使得特殊字符在预留空间部分进行跑动。由于printf默认字符串输出为右对齐,特殊字符从右向左输出打印,可以使
-
表示左对齐,解决这个问题。[%3d%%]:添加比例,确保进度条进度卡住,通过旋转光标得知,进度条还是进行。同时添加数字,确保有充足空间。
[const char *lable ="|/-\ \ " ] :这里\
需要使用\
的字面值
3.2 下载场景
由于进度条需要配合场景进行使用,现在我们设计一个下载文件的场景。
3.2.1 Main.c
cpp
void download()
{
double filesize = 100 * 1024 * 1024 * 1.0;//下载文件总大小
double current = 0.0;//当前下载进度
double bandwidth = 1024 * 1024 * 1.0;//带宽
printf("download begin, current: %lf\n", current);
while (current <= filesize)
{
ProcessBar(filesize, current);
usleep(100000);
current += bandwidth;
}
printf("\ndownload done, filesize: %lf\n", filesize);
}
int main()
{
download();
return 0;
}
这里提示信息会将部分进度条冲掉,可以采用\n换行打印。
3.2.2 Version2:进度条实现
cpp
#include "Processbar.h"
#define Length 101//设计缓冲区长度,其中为'\0'多开一块空间
#define Style '#'//设计进度条状态,显示特殊字符
const char* lable = "|/-\\";
//version2
void ProcessBar(double total,double current)
{
char bar[Length];//定义缓冲区
memset(bar,'\0', sizeof(bar));//设置缓冲区初始数值,清空缓冲区数据操作
int len = strlen(lable);
int cnt = 0;
double rate = (100 * current) / total;//进度
int loop_count = (int)rate;//循环次数
while (cnt <= loop_count)
{
bar[cnt++] = Style;
}
printf("[%-100s][%.1lf%%][%c]\r", bar, rate, lable[cnt % len]);
fflush(stdout);
}
【打印出现卡顿情况】
由于ProcessBar在外部会被不断调用,导致多次从头开始打印。这里可以将printf("[%-100s][%.1lf%%][%c]\r", bar, rate, lable[cnt % len]);
提取出来。在循环体内,将字符串拼接好,放到缓冲区中,根据外部比例,只需要每次打印一张静态的进度条。
【不同风格的代码】
如果以后我们想在不改变源代码的基础上,使用其他形式进度条。比如:图形界面版的进度条使用起来,这里可以将函数作为参数,只需要传递函数指针即可。
模拟网络是否良好,可以在外部调用不同大小文件。
以上就是本篇文章的所有内容,在此感谢大家的观看!这里是Linux笔记,希望对你在学习Linux旅途中有所帮助!