当前位置: 首页 > news >正文

【Linux】Linux第一个小程序 - 进度条

 🔥 脏脏a的技术站 🔥
 
「在代码的世界里,脏脏的技术探索从不设限~」

🚀 个人主页:脏脏a-CSDN博客

📌 技术聚焦:Linux下第一个小程序:进度条
📊 文章专栏:Linux

🔗 上篇回顾:Linux自动化构建工具:make/Makefile

在 Linux 世界开启编程之旅,从一个动态进度条小程序,带你吃透回车换行与行缓冲的底层奥秘。

目录

一、前置知识

1.1 回车和换行

1.2 缓冲区(简单了解)

二、实现简单的倒计时

三、进度条

3.1 Verrsion1版本

3.2 进度条在下载场景下的应用


一、前置知识

1.1 回车和换行

在学习 C 语言时,我们常认为 \n 只是 “换行”—— 让光标移到下一行开头。但实际上,它隐含了回车换行两个动作,二者的职责截然不同:

  • 回车(\r):使光标回到当前行的开头
  • 换行(\n):使光标跳转到下一行的当前列位置

1.2 缓冲区(简单了解)

缓冲区就是内存里一个 “临时放东西的小仓库”。

比如你用 printf 打印文字时,文字不会立马显示在屏幕上,而是先堆在这个 “小仓库” 里。

啥时候才显示呢?要么仓库堆满了,要么你打了个换行 \n(换行有刷新缓冲区的作用),要么程序跑完了 —— 这时候 “仓库” 才把东西一次性搬出来给你看。

简单说,就是先攒一攒,再一起处理,省事儿又高效。

二、实现简单的倒计时

#include<stdio.h>   // 包含标准输入输出库,提供 printf、fflush 等函数 
#include<unistd.h>  // 包含 Unix 标准库,提供 sleep 函数(Linux 系统专用)int main()
{int cnt = 9;               // 定义倒计时起始值为 9while(cnt >= 0)            // 循环条件:当倒计时未结束(cnt 大于等于 0 时){printf("%d\r", cnt);   // 打印当前倒计时数值,并通过 \r(回车)使光标回到行首// 这样后续输出会覆盖当前行,实现“同一行刷新”效果fflush(stdout);        // 强制刷新标准输出缓冲区,确保数值立即显示(避免缓冲延迟)sleep(1);              // 程序暂停 1 秒(Linux 下 sleep 单位为秒)cnt--;                 // 倒计时数值减 1}printf("\n");  // 倒计时结束后,输出换行符,使光标移至下一行(避免后续输出覆盖)return 0;
}

程序在终端以每秒一次的频率,在同一行动态刷新显示从 9 到 0 的倒计时,结束后换行。

#include<stdio.h>   // 包含标准输入输出库,提供 printf、fflush 等函数
#include<unistd.h>  // 包含 Unix 标准库,提供 sleep 函数(Linux 系统专用)int main()
{int cnt = 11;              // 定义倒计时起始值为 11while(cnt >= 0)            {printf("%2d\r", cnt);  // 打印当前倒计时数值(%2d 确保数字占 2 个字符宽度,对齐显示)// \r(回车符)使光标回到当前行首,后续输出会覆盖本行内容// 实现“同一行动态刷新”的倒计时效果fflush(stdout);        // 强制刷新标准输出缓冲区,确保数值立即显示(避免因缓冲导致的延迟)sleep(1);              // 程序暂停 1 秒(Linux 环境下 sleep 函数单位为秒)cnt--;                 // 倒计时数值减 1}printf("\n");  // 倒计时结束后,输出换行符,使光标移至下一行(避免后续内容与倒计时在同一行)return 0;
}

当倒计时从 11 开始,若用%d输出,两位数(如 10)变为一位数(如 9)时,前一个数的末尾字符(如 “0”)无法被完全覆盖,会出现 “90”“80” 等错误显示。而%2d会强制让数字占 2 个字符宽度,不足时补空格,确保后一个数字能完全覆盖前一个,避免错位问题。

三、进度条

进度条初步设想:

【Makefile文件】:

我们这是按声明放在头文件,定义放在源文件的写法写的,有些同学可能会疑问为啥依赖关系中没有头文件,这是因为源文件和头文件在同一个目录下,而源文件中包含的头文件,所以编译器自己能找到头文件

3.1 Verrsion1版本

//progressbar.h#include<stdio.h> //printf fflush
#include<unistd.h> //unsleep 单位:微秒
#include<string.h> //strlen
#define NUM  101 //多给'\0'留了一个位置
#define pro  '=' //进度条款式void progressbar();
//progressbar.c#include"progressbar.h"const char* str = "\\|/-";//旋转光标的棍棍 \\是转义字符'\'void progressbar()
{char bar[NUM] = {0};//把数组先全部初始化为\0int len = strlen(str);int cnt = 100;while(cnt<=100){printf("[%-100s][%d%%][%c]\r",bar,cnt,str[cnt%len]);fflush(stdout);bar[cnt++] = pro;if(cnt<100)//避免越界,下标为100的位置是给\0预留的位置,覆盖了可能导致程序崩溃bar[cnt] = '>';usleep(50000);}printf("\n");
}
#include"progressbar.h"int main()
{progressbar();return 0;
}

【第一个版本运行完的结果】:

[进度条数组与越界控制]:

char bar[NUM] 存储进度字符,if(cnt<100) 限制 bar[cnt] = '>' 仅在合法下标内执行,避免越界覆盖终止符 \0

[旋转光标逻辑]:

str = "\\|/-" 定义旋转字符,str[cnt%len] 通过取模循环切换字符,实现动态旋转效果,len 确保下标合法。

[进度节奏控制]:

usleep(50000) 暂停 50 毫秒,平衡进度条刷新速度与 CPU 占用,让进度变化直观可见。

 3.2 进度条在下载场景下的应用

【progressbar.h】:

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#define NUM 101
#define pro '='void progressbar(int date);
void initbar();

【progressbar.c】:

#include"progressbar.h"const char* str = "\\|/-";
char bar[NUM] = {0};void progressbar(int rate)
{if(rate<0 || rate>100) return ;int len = strlen(str);printf("[%-100s][%d%%][%c]\r",bar,rate,str[rate%len]);fflush(stdout);bar[rate++] = pro;if(rate<100)bar[rate] = '>';
}void initbar()
{memset(bar, '\0', sizeof(bar));
}

【main.c】:

typedef void (*call)(int);void downLoad(call ca) 
{int total = 1000; // 1000MBint cnt = 0;      // 0MBwhile (cnt <= total) {usleep(50000); // 模拟下载时间int rate = cnt * 100 / total; // 更新进度ca(rate); // 通过回调,展示进度cnt += 10; // 循环下载了一部分}printf("\n");
}int main() 
{printf("download 1: \n");downLoad(progressbar);initbar();printf("download 2: \n");downLoad(progressbar);initbar();printf("download 3: \n");downLoad(progressbar);initbar();printf("download 4: \n");downLoad(progressbar);initbar();printf("\nDownload complete!!!\n");return 0;
}

【应用场景版本运行结果】:

[进度条数组与越界控制]:

char bar[NUM] 存储进度字符,if(rate<100) 限制 bar[rate] = '>' 仅在合法下标执行,避免越界覆盖终止符 \0

[旋转光标逻辑]:

str = "\\|/-" 定义旋转字符,str[rate%len] 通过取模循环切换字符,实现动态旋转效果,len 确保下标合法。

[进度刷新与缓冲控制]:

printf 中 \r 使光标回退覆盖旧内容,fflush(stdout) 强制刷新缓冲区,保证进度条实时可见。

[下载回调与进度计算]:

downLoad 中 rate = cnt*100/total 计算进度百分比,通过函数指针 ca(rate) 回调 progressbar 展示进度,cnt+=10 模拟分段下载。

[数组初始化逻辑]:

initbar 中 memset(bar, '\0', sizeof(bar)) 初始化进度条数组,避免多次下载时状态残留。

这种应用场景就是利用回调函数实现多次下载

http://www.dtcms.com/a/560907.html

相关文章:

  • ubuntu新增用户
  • 青州市网站建设长沙招聘网58同城招聘发布
  • 江苏中南建设集团网站是多少长沙互联网网站建设
  • 从零开始的云原生之旅(十一):压测实战:验证弹性伸缩效果
  • 民宿网站的建设wordpress gallery
  • 【开题答辩全过程】以 广州网红点打卡介绍网站为例,包含答辩的问题和答案
  • Taro 源码浅析
  • Chart.js 混合图:深度解析与应用技巧
  • redis 大key、热key优化技巧|空间存储优化|调优技巧(一)
  • 监视你的脚本:自动 Linux 活动审计
  • 15.1.2.linux常见操作用例
  • 【Java Web学习 | 第五篇】CSS(4) -盒子模型
  • ubuntu samba 快速安装启用
  • 【数据结构】用顺序表实现通讯录
  • cpp / c++零基础就业学习一站式学习平台
  • FreeRTOS(二)
  • 开源AI智能名片链动2+1模式S2B2C商城小程序商业化路径优化研究
  • 中国优秀的企业网站做搜狐网站页面
  • 【效率工具】EXCEL批注提取工具
  • Python openpyxl 设置Excel单元格公式和工作簿合并
  • 作文生成器网站北京seo招聘信息
  • 常州网站设计制作贵美商城网站的首页怎么做代码
  • 新媒体矩阵系统全景解析:赋能企业数字化营销的智能引擎
  • 多目标优化问题在适应度计算中的支配矩阵
  • 从零开始的云原生之旅(九):云原生的核心优势:自动弹性伸缩实战
  • 【Swift】LeetCode 240.搜索二维矩阵 II
  • 矩阵(板子)
  • 防火墙的内容补充
  • C++类和对象(下):初始化列表
  • 建筑工程找活网站wordpress文章新窗口