【Linux基础开发工具 (六)】Linux中的第一个系统程序——进度条Linux:详解回车、换行与缓冲区

【Linux基础开发工具 (六)】Linux中的第一个系统程序——进度条Linux:详解回车、换行与缓冲区

在这里插入图片描述


🎬 个人主页艾莉丝努力练剑
专栏传送门:《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录
Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享

⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平


🎬 艾莉丝的简介:

在这里插入图片描述

🎬 艾莉丝的Linux专栏简介:
​​​​

在这里插入图片描述

文章目录


在这里插入图片描述

在这里插入图片描述

5 ~> Linux中的第一个系统程序:进度条

5.1 两个储备知识:回车换行 / 缓冲区

5.1.1 回车和换行是一码事吗?

回车和换行不是一码事。

这是一张普通的作文纸,每次我们写完一行,都要从下一行开头开始继续往下写,写完一段,都要新起一行——

在这里插入图片描述

如下图,键盘、打字机上面都有回车键——

在这里插入图片描述
在这里插入图片描述

为什么说回车和换行不是一回事呢?

在这里插入图片描述


是的,回车换行是两个动作,\r是回车,\n是换行(和\r\n是一样的),在C/C++里面\n(C)、std::endl(C++)是把两个动作(回车和换行)合写成一个一个了。

5.1.2 缓冲区

[Alice@VM-4-17-centos Ludy]$ vim code.c [Alice@VM-4-17-centos Ludy]$ make 我要开始编译了...code.c -> code.o 我要开始链接了...code.o -> code.exe [Alice@VM-4-17-centos Ludy]$ ./code.exe hello world![Alice@VM-4-17-centos Ludy]$ 
在这里插入图片描述

这里就是字符位数不够,右对齐了——

在这里插入图片描述
在这里插入图片描述
fflush(stdout);# 强制刷新缓冲区
在这里插入图片描述
在这里插入图片描述

5.2 观察:行缓冲区

下面的代码会有哪些现象?

#include <stdio.h> int main(){ printf("hello Alice!\n"); sleep(3);return0;}
#include <stdio.h> int main(){ printf("hello Alice!"); sleep(3);return0;}
#include <stdio.h> int main(){ printf("hello Alice!"); fflush(stdout); sleep(3);return0;}

5.3 练练手:demo:光标快速回退,完成倒计时功能

5.3.1 代码演示

在这里插入图片描述
1#include <stdio.h>2#include <unistd.h>34 //int a =0;5 //scanf("%d",&a);67 int main()8{9 int cnt =10;10 for(;cnt >=0;cnt--)11{12 printf("倒计时:%-2d\r",cnt); // 10:10,'1''0',字符,printf做的—>格式化输出!putc 13 fflush(stdout); // 强制刷新缓存 14 sleep(1);15}16 printf("\n");1718return0;19}2021 //int main()22 //{23 // printf("hello world!");24 // fflush(stdout);25 // sleep(1);26 // 27 // return0;28 //}

5.3.2 最终效果呈现

[Alice@VM-4-17-centos Ludy]$ make 我要开始编译了...code.c -> code.o 我要开始链接了...code.o -> code.exe [Alice@VM-4-17-centos Ludy]$ ./code.exe 倒计时:0 
在这里插入图片描述

5.4 进度条(两种方式,这里只演示后一种)

进度条是用户界面中常见的元素,用于直观展示任务的完成进度。接下来,艾莉丝会介绍如何使用C语言在Linux操作系统中(centos版本)实现一个功能完整的进度条——也是我们介绍的Linux中的第一个系统程序。

5.4.1 Makefile

1Bin=process_bar 2Cc=gcc 3Src=$(wildcard *.c)4Obj=$(Src:.c=.o)56# @:不回显78$(Bin):$(Obj)9 @echo "$^ link to $@"10 @$(Cc) -o $@ $^ 11 %.o:%.c 12 @echo "compling $< to $@"13 @$(Cc) -c $<1415 .PHONY:clean 16 clean: 17 @echo "Clean Project...Done"18 @rm -f $(Obj)$(Bin)1920 .PHONY:Print 21 Print: 22 @echo $(Bin)23 @echo $(Cc)24 @echo $(Src)25 @echo $(Obj)

5.4.2 Process.h

定义函数指针类型flush_t,支持回调机制。

声明进度条显示函数接口。

total - 总任务量:表示需要完成的全部工作量;
current - 当前完成量:表示已经完成的工作量;
speed - 当前速度:表示单位时间内完成的工作量;
userinfo - 用户信息:这里表示速度单位:“MB/s”

1 //#ifndef PROCESS_H2 //#define PROCESS_H3 // 4 //#include<stdio.h>5 // 6 //// ANSI 颜色代码 7 //#define COLOR_RED "\033[31m"8 //#define COLOR_GREEN "\033[32m"9 //#define COLOR_YELLOW "\033[33m"10 //#define COLOR_BLUE "\033[34m"11 //#define COLOR_MAGENTA "\033[35m"12 //#define COLOR_CYAN "\033[36m"13 //#define COLOR_RESET "\033[0m"14 // 15 //typedef void (*flush_t)(double total,double current,double speed,const char* userinfo);16 // 17 //void Process(double total,double current,double speed,const char* userinfo);18 // 19 //#endif2021#ifndef PROCESS_H22#define PROCESS_H2324 // ANSI 颜色代码 25#define COLOR_RED "\033[31m"26#define COLOR_GREEN "\033[32m"27#define COLOR_YELLOW "\033[33m"28#define COLOR_BLUE "\033[34m"29#define COLOR_MAGENTA "\033[35m"30#define COLOR_CYAN "\033[36m"31#define COLOR_RESET "\033[0m"3233 typedef void (*flush_t)(double total,double current,double speed,const char* userinfo);3435 void Process(double total,double current,double speed,const char* userinfo);3637#endif 

5.4.3 Process.c

1、 百分比计算: current * 100.0 / total

2、 进度条填充: 使用循环填充 - 字符

3、 旋转光标: 通过字符序列|\\-/实现动画效果

4、 实时刷新: 使用\r回车符和fflush(stdout)实现原地更新

1#include "process.h"2#include <stdio.h>3#include <string.h>4#include <unistd.h>56 // 如果头文件中没有定义颜色,则在这里定义 7#ifndef COLOR_RED8#define COLOR_RED "\033[31m"9#define COLOR_GREEN "\033[32m"10#define COLOR_YELLOW "\033[33m"11#define COLOR_BLUE "\033[34m"12#define COLOR_MAGENTA "\033[35m"13#define COLOR_CYAN "\033[36m"14#define COLOR_RESET "\033[0m"15#endif1617#define SIZE 10218#define LABEL '='1920 void Process(double total, double current, double speed, const char* userinfo)21{22 if(current > total)23return;2425 // 旋转光标 26 static const char* lable ="|/-\\";27 static int index =0;28 int size = strlen(lable);2930 // 下载比率 31 double rate = current * 100.0 / total;32 char out_bar[SIZE];33 memset(out_bar, '\0', sizeof(out_bar));3435 // 填充进度字符 36 int i =0;37 int bar_length =(int)rate;38 if(bar_length >100) bar_length =100;39 for(; i < bar_length; i++)40{41 out_bar[i]= LABEL;42}4344 // 选择颜色基于进度 45 const char* color;46 if(rate <30.0)47 color = COLOR_RED;48else if(rate <70.0)49 color = COLOR_YELLOW;50else51 color = COLOR_GREEN;5253 // 修复:在 printf 开头添加颜色变量 54 // 刷新进度条 - 使用 \r 确保不换行 55 printf("\r[%-100s] %5.1f%% [%c] %.1f/%.1f speed:%.1f %s", 56 out_bar, rate, lable[index], current, total, speed, userinfo);57 fflush(stdout);5859 index++;60 index %= size;6162 // 进度条完成,记得换行 63 if(current >= total)64{65 printf("\n");66}67}6869 //#include"process.h"70 //#include<stdlib.h>71 //#include<string.h>72 //#include<stdio.h>73 //#include<unistd.h>74 // 75 //#define SIZE 10376 //#define LABLE '='77 // 78 //void Process(double total,double current,double speed,const char* userinfo)79 //{80 // if(current > total)81 // return;82 // 83 // // 旋转光标和下载本身有关吗?Process函数是否被调用有关 84 // static const char* lable ="|/-\\";85 // static int index =0;86 // int size = strlen(lable);87 // // 绝对不能一次循环就把整个进度条下载完毕 88 // // 1、下载比率,10.4 89 // double rate = current*100.0/total; // 45.0 / 100.0=0.45,0.45 * 100.0=45.090 // char out_bar[SIZE];91 // memset(out_bar,'\0',sizeof(out_bar));92 // 93 // // 2、填充进度字符 94 // int i =0;95 // int bar_length =(int)rate;96 // if(bar_length >100) bar_length =100;97 // for(; i < bar_length; i++)98 // 99 // out_bar[i]= LABLE;100 // }101 // 102 // // 选择颜色基于进度 103 // const char* color;104 // if(rate <30.0)105 // color = COLOR_RED;106 // else if(rate <70.0)107 // color = COLOR_YELLOW;108 // else109 // color = COLOR_GREEN;110 // 111 // // 3、刷新进度条 112 // printf("[%-100s][%5.1lf%%][%c] | %.1lf/%.1lf,speed:%.1lf%s\r",\113 // color, out_bar,rate,lable[index],current,total,speed,userinfo,COLOR_RESET);114 // 115 // fflush(stdout);116 // index++;117 // index %= size;118 // 119 // // 4、进度条完成,记得换行 120 // if(current >= total)121 // printf("\r\n");122 // //printf("\n");123 //}124125 //// 进度条的版本一-->version1版本 126 //void Processversion1()127 //{128 // const char* lable ="\\|/-";129 // int len = strlen(lable);130 // char out_bar[SIZE];131 // memset(out_bar,'\0',sizeof(out_bar));132 // while(cnt <=100)133 // {134 // printf("[%-100s][%3d%%][%c]\r",out_bar,cnt,lable[cnt % len]);135 // fflush(stdout);136 // out_bar[cnt]= LABLE;137 // cnt++;138 // 139 // usleep(30000);140 // }141 // 142 // printf("\r\n");143 //}144145 //void Process()146 //{147 // const char* lable[]={148 // "loading.", 149 // "loading..", 150 // "loading...", 151 // };152 // 153 // int size = sizeof(lable) / sizeof(lable[0]);154 // int cnt =0;155 // char out_bar[SIZE];156 // memset(out_bar,'\0',sizeof(out_bar));157 // while(cnt <=100)158 // {159 // printf("[%-100s][%3d%%][%-7s]\r",out_bar,cnt,lable[cnt%size]);160 // fflush(stdout);161 // out_bar[cnt]= LABLE;162 // cnt++;163 // 164 // usleep(1000000);165 // }166 // printf("\r\n");167 //}

5.4.4 main.c

1#include"process.h"2#include<unistd.h>3#include<stdlib.h>4#include<time.h>5#include<stdio.h>67 // 有一个下载任务 8 double gtotal =1024.0; // 目标文件的总大小 9 double gspeed =1.0; // 下载时的网络速度 1011 // 回调函数 12 void Download(double total,flush_t cb)13{14 double level[]={0.5,1.0,2.0,5.0,10.0,20.0,30.0,30.0,40.5,80.5};15 int num = sizeof(level) / sizeof(level[0]);1617 double current =0.0; // 当前下载了多少 18 while(1)19{20 usleep(100000); // 模拟下载,单位微秒 21 double speed = level[rand()%num]; // 随机网速 22 current += speed;23 if(current >= total)24{25 current = total;26 cb(total,current,speed,"MB/s"); // 更新进度条 27break;28}29 else{30 cb(total,current,speed,"MB/s"); // 更新进度条 31}32}33}3435 // 添加进度条色块 3637 int main()38{39 //// version 40 // Process(); // 进度条程序 4142 srand(time(NULL));43 // 多个不同大小程序的下载 44 printf("download:\n");45 Download(gtotal,Process);4647 printf("download:\n");48 Download(120.0,Process);4950 printf("download:\n");51 Download(11.8,Process);5253 printf("download:\n");54 Download(78.9,Process);5556 printf("download:\n");57 Download(900.0,Process);585960return0;61}

5.5 数据流动示意图

初始化阶段 ↓ total =1024.0(总任务量) ↓ 循环更新阶段 ↓ current =0 → 逐渐增加 → total (当前进度) speed = 随机值 (实时速度) userinfo ="MB/s"(单位信息) ↓ 显示阶段 ↓ [----------][45.5%][\]|465.9/1024.0, speed:25.3MB/s 

5.6 效果演示

5.6.1 静态效果

在这里插入图片描述

5.6.2 动态效果

到博客创作玩之前,艾莉丝只写了无色的进度条的版本

进度条(无色)


结尾

uu们,本文的内容到这里就全部结束了,艾莉丝再次感谢您的阅读!

结语:希望对学习Linux相关内容的uu有所帮助,不要忘记给博主“一键四连”哦!

往期回顾:

【Linux基础开发工具 (五)】详解自动化构建:make / Makefile

🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡૮₍ ˶ ˊ ᴥ ˋ˶₎ა

Read more

AI Agent新范式:FastGPT+MCP协议实现工具增强型智能体构建

AI Agent新范式:FastGPT+MCP协议实现工具增强型智能体构建

AI Agent新范式:FastGPT+MCP协议实现工具增强型智能体构建 作者:高瑞冬 本文目录 * AI Agent新范式:FastGPT+MCP协议实现工具增强型智能体构建 * 一、MCP协议简介 * 二、创建MCP工具集 * 1. 获取MCP服务地址 * 2. 在FastGPT中创建MCP工具集 * 三、测试MCP工具 * 四、AI模型调用MCP工具 * 1. 调用单个工具 * 2. 调用整个工具集 * 五、私有化部署支持 * 1. 环境准备 * 2. 修改docker-compose.yml文件 * 3. 修改FastGPT配置 * 4. 重启服务 * 六、使用MCP-Proxy集成多个MCP服务 * 1. MCP-Proxy简介 * 2. 安装MCP-Proxy * 3. 配置MCP-Proxy * 4. 将MCP-Proxy与FastGPT集成 * 5. 高级配置

By Ne0inhk
【大模型实战篇】基于Claude MCP协议的智能体落地示例

【大模型实战篇】基于Claude MCP协议的智能体落地示例

1. 背景         之前我们在《MCP(Model Context Protocol) 大模型智能体第一个开源标准协议》一文中,介绍了MCP的概念,虽然了解了其概念、架构、解决的问题,但还缺少具体的示例,来帮助进一步理解整套MCP框架如何落地。         今天我们基于claude的官方例子--获取天气预报【1】,来理解MCP落地的整条链路。 2. MCP示例         该案例是构建一个简单的MCP天气预报服务器,并将其连接到主机,即Claude for Desktop。从基本设置开始,然后逐步发展到更复杂的使用场景。         大模型虽然能力非常强,但其弊端就是内容是过时的,这里的过时不是说内容很旧,只是表达内容具有非实时性。比如没有获取天气预报和严重天气警报的能力。因此我们将使用MCP来解决这一问题。         构建一个服务器,该服务器提供两个工具:获取警报(get-alerts)和获取预报(get-forecast)。然后,将该服务器连接到MCP主机(在本例中为Claude for Desktop)。         首先我们配置下环

By Ne0inhk
基于腾讯云HAI + DeepSeek快速设计自己的个人网页

基于腾讯云HAI + DeepSeek快速设计自己的个人网页

前言:通过结合腾讯云HAI 强大的云端运算能力与DeepSeek先进的 AI技术,本文介绍高效、便捷且低成本的设计一个自己的个人网页。你将了解到如何轻松绕过常见的技术阻碍,在腾讯云HAI平台上快速部署DeepSeek模型,仅需简单几步,就能获取一个包含个人简介、技能特长、项目经历及联系方式等核心板块的响应式网页。 目录 一、DeepSeek模型部署在腾讯云HAI 二、设计个人网页 一、DeepSeek模型部署在腾讯云HAI 把 DeepSeek 模型部署于腾讯云 HAI,用户便能避开官网访问限制,直接依托腾讯云 HAI 的超强算力运行 DeepSeek-R1 等模型。这一举措不仅降低了技术门槛,还缩短了部署时间,削减了成本。尤为关键的是,凭借 HAI 平台灵活且可扩展的特性,用户能够依据自身特定需求定制专属解决方案,进而更出色地适配特定业务场景,满足各类技术要求 。 点击访问腾讯云HAI控制台地址: 算力管理 - 高性能应用服务 - 控制台 腾讯云高性能应用服务HAI已支持DeepSeek-R1模型预装环境和CPU算力,只需简单的几步就能调用DeepSeek - R1

By Ne0inhk
AI革命先锋:DeepSeek与蓝耘通义万相2.1的无缝融合引领行业智能化变革

AI革命先锋:DeepSeek与蓝耘通义万相2.1的无缝融合引领行业智能化变革

云边有个稻草人-ZEEKLOG博客 目录 引言 一、什么是DeepSeek? 1.1 DeepSeek平台概述 1.2 DeepSeek的核心功能与技术 二、蓝耘通义万相2.1概述 2.1 蓝耘科技简介 2.2 蓝耘通义万相2.1的功能与优势 1. 全链条智能化解决方案 2. 强大的数据处理能力 3. 高效的模型训练与优化 4. 自动化推理与部署 5. 行业专用解决方案 三、蓝耘通义万相2.1与DeepSeek的对比分析 3.1 核心区别 3.2 结合使用的优势 四、蓝耘注册流程 五、DeepSeek与蓝耘通义万相2.1的集成应用 5.1 集成应用场景 1. 智能医疗诊断

By Ne0inhk