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

【Linux】LInux下第一个程序:进度条

前言:

        在前面的文章中我们学习了LInux的基础指令

      【Linux】初见,基础指令-CSDN博客【Linux】初见,基础指令(续)-CSDN博客

        学习了vim编辑器【Linux】vim编辑器_linux vim insert-CSDN博客

        学习了gcc/g++【Linux】编译器gcc/g++及其库的详细介绍-CSDN博客

        以及make/makefile【Linux】自动化构建-Make/Makefile-CSDN博客

有了以上知识的铺垫,我们终于可以开始在Linux上编写运行我们的代码,于是我们来到了Linux下的第一个程序:进度条

1.回车换行符 

       大多数人可能觉得"回车换行"这一词指的是同一个东西。但其实回车是回车、换行是换行,这两个有本质区别。

        我们日常使用的回车键合成了"回车"和"换行"功能,这就导致了大家觉得这是一个东西。

回车的符号为:\n
回车的功能是将光标重置到最开始位置

换行的符号为:\r 
换行的功能是将光标下移一行

2.缓冲区问题

什么是缓冲区?

        缓冲区是系统预留的内存区域,其作用是暂时存放输入或输出的数据。引入缓冲区主要是为了平衡高速的 CPU 与低速的 I/O 设备之间的速度差异,进而提升系统的整体性能。

刷新缓冲区?

        通常情况下,数据会先被存储在缓冲区中,只有当缓冲区满、遇到特定的控制字符,或者程序运行结束时,才会将数据真正写入目标设备。不过,在某些特定场景下,可能需要手动刷新缓冲区,以确保数据能及时输出。

举例:

//代码1
#include<stdio.h>
#include<unistd.h>
int main()
{printf("hello\n");                                                                                                                                       sleep(3);    
}//代码2
#include<stdio.h>
#include<unistd.h>
int main()
{                                                                                                                            printf("hello");sleep(3);    
}

运行代码1:我们可以看到显示屏上马上显示出"hello",然后停滞3秒结束程序

运行代码2:我们看到是恰恰相反,先停滞3秒后打印出"hello",然后结束程序

这个就是缓冲区的问题:"\n"可以马上刷新缓冲区,所以代码1可以马上显示。而没有"\n",就无法马上刷新缓冲区,当整个程序结束后系统自动刷新,显示"hello"

那如何使其马上刷新?

fflush(stdout)

3.预备代码

先创建文件夹,并在文件夹中创建相应的.c .h文件

hyc@hcss-ecs-4ce7:~$ mkdir progress
hyc@hcss-ecs-4ce7:~$ cd progress
hyc@hcss-ecs-4ce7:~/progress$ touch p.c p.h main.c

编写代码,与makefile。进度条只会在一行打印,所以我们不能使用 \n,而是使用 \r,在同一行打印

但是当我们运行代码时,发现并没有显示结果。这是因为当前数据还在缓冲区没有刷新出来,我们使用ffulsh(stdout)使其马上刷新

这时我们可以看到结果:在同一位置上显示

4.进度条代码

4.1首先先看看我们想实现一个什么样子的进度条

4.2代码实现 

我们一步一步来,先实现左侧部分

1.考虑使用字符数组来表示递增的进度条。先将字符数组初始化为 ‘\0’,通过%s打印时遇到 ‘\0’就会停止。

2.通过计数器计数,来计算输出多少符号

3.通过fflush(stdout)立马刷新缓冲区,让我们看到结果

4.通过sleep让我们看到其过程

5.最后为了避免命令行覆盖我们输出的内容,进行换行操作

最后添加一下左右中括号,修改一下细节问题:

打印进度条使用%-100s占位符

sleep有点太慢了,我们可以使用usleep

#include"p.h"
#include<unistd.h>
#include<string.h>void progress_v1()
{char arr[101];memset(arr,'\0',sizeof(arr));int num=0;for(int i=0;i<=101;i++){   arr[num]='X';printf("[%-100s]\r",arr);fflush(stdout);usleep(10000);num++;}   printf("\n");
}  

效果

接下来我们就可以来考虑一下百分比和旋转光标了

1.百分比直接去计算就好了,没什么好说的。

2.旋转光标:我们不要去想复杂了,动态的本质其实就是一帧一帧的静态图像,我们只需要写一个字符数组x,然后不断的打印字符,就可以实现旋转光标了。 

#include<stdio.h>
#include<unistd.h>
#include<string.h>void progress_v1()
{char arr[101];char x[]={'/','-','\\','\0'};memset(arr,'\0',sizeof(arr));int num=0;for(int i=0;i<=101;i++){   arr[num]='X';printf("[%-100s][%.2f][%c]\r",arr,num*1.0/sizeof(arr)*100,x[num%3]);fflush(stdout);usleep(10000);num++;}   printf("\n");
}  

效果演示:

5.模拟真实环境

一个真正的进度条不可能就我们上面写的代码一样自顾自的打印。应该是根据实际情况,一边下载(或其他操作),一边打印进度条。

于是我们实现一个download函数模拟实时下载环境 

total:表示一共想要下载的量

speed:表示单次下载的速度

每下载一次就更新一次进度条

通过实时的下载量来计算进度条中需要打印的个数,以及百分比。 

代码汇总: 

//p.h#include<stdio.h>
void progress_v1();
void progress_v2(double cur,double total);        //p.c#include"p.h"
#include<unistd.h>
#include<string.h>void progress_v1()
{char arr[101];char x[]={'/','-','\\','\0'};memset(arr,'\0',sizeof(arr));int num=0;for(int i=0;i<=101;i++){arr[num]='X';printf("[%-100s][%.2f][%c]\r",arr,num*1.0/sizeof(arr)*100,x[num%3]);fflush(stdout);usleep(10000);num++;}   printf("\n");
}void progress_v2(double cur,double total)
{char arr[101];char x[]={'/','-','\\','\0'};memset(arr,'\0',sizeof(arr));//get the numberint num=(int)(cur*100/total);for(int i=0;i<num;i++){   arr[i]='X';}   printf("[%-100s][%.2f][%c]\r",arr,cur*100/total,x[num%3]);fflush(stdout);
}//main.c#include <stdio.h>
int main()
{printf("Hello world\n");return 0;
}                                                                                                                                         

相关文章:

【Linux】LInux下第一个程序:进度条

前言&#xff1a; 在前面的文章中我们学习了LInux的基础指令 【Linux】初见&#xff0c;基础指令-CSDN博客【Linux】初见&#xff0c;基础指令&#xff08;续&#xff09;-CSDN博客 学习了vim编辑器【Linux】vim编辑器_linux vim insert-CSDN博客 学习了gcc/g【Linux】编译器gc…...

RPA+AI:自动化办公机器人开发指南

RPAAI&#xff1a;自动化办公机器人开发指南 系统化学习人工智能网站&#xff08;收藏&#xff09;&#xff1a;https://www.captainbed.cn/flu 文章目录 RPAAI&#xff1a;自动化办公机器人开发指南摘要引言技术融合路径1. 传感器层&#xff1a;多模态数据接入2. 决策层&…...

daz3d + PBRSkin (MDL)+ SSS

好的&#xff0c;我们来解释一下 Daz3D 中的 PBRSkin (MDL) Shader。 简单来说&#xff0c;PBRSkin (MDL) 是 Daz Studio 中一种基于物理渲染&#xff08;PBR&#xff09;技术、专门用于创建高度逼真人物皮肤效果的着色器&#xff08;Shader&#xff09;。 它利用 NVIDIA 的材…...

计算矩阵A和B的乘积

根据矩阵乘法规则&#xff0c;编程计算矩阵的乘积。函数fix_prod_ele()是基本方法编写&#xff0c;函数fix_prod_opt()是优化方法编写。 程序代码 #define N 3 #define M 4 typedef int fix_matrix1[N][M]; typedef int fix_matrix2[M][N]; int fix_prod_ele(f…...

Houdini POP入门学习05 - 物理属性

接下来随着教程学习碰撞部分&#xff0c;当粒子较为复杂或者下载了一些粒子模板进行修改时&#xff0c;会遇到一些较奇怪问题&#xff0c;如粒子穿透等&#xff0c;这些问题实际上可以通过调节参数解决。 hip资源文件&#xff1a;https://download.csdn.net/download/grayrail…...

每日Prompt:双重曝光

提示词 新中式&#xff0c;这幅图像将人体头像轮廓与山水中式建筑融为一体&#xff0c;双重曝光&#xff0c;体现了反思、内心平静以及人与自然相互联系的主题&#xff0c;靛蓝&#xff0c;水墨画&#xff0c;晕染&#xff0c;极简...

sendDefaultImpl call timeout(rocketmq)

rocketmq 连接异常 senddefaultimpl call timeout-腾讯云开发者社区-腾讯云 第一种情况&#xff1a; 修改broker 的配置如下&#xff0c;注意brokerIP1 这个配置必须有&#xff0c;不然 rocketmq-console 显示依然是内网地址 caused by: org.apache.rocketmq.remoting.excep…...

【LLM】多智能体系统 Why Do Multi-Agent LLM Systems Fail?

note 构建一个成功的 MAS&#xff0c;不仅仅是提升底层 LLM 的智能那么简单&#xff0c;它更像是在构建一个组织。如果组织结构、沟通协议、权责分配、质量控制流程设计不当&#xff0c;即使每个成员&#xff08;智能体&#xff09;都很“聪明”&#xff0c;整个系统也可能像一…...

CSS 定位:原理 + 场景 + 示例全解析

一. 什么是CSS定位? CSS中的position属性用于设置元素的定位方式,它决定了元素在页面中的"定位行为" 为什么需要定位? 常规布局(如 display: block)适用于主结构 定位适用于浮动按钮,弹出层,粘性标题等场景帮助我们精确控制元素在页面中的位置 二. 定位类型全…...

如何在没有 iTunes 的情况下备份 iPhone

我可以在没有 iTunes 的情况下将 iPhone 备份到电脑吗&#xff1f;虽然 iTunes 曾经是备份 iPhone 的主要方法&#xff0c;但它并不是 iOS 用户唯一的备份选项。您可以选择多种方便的替代方案来备份 iPhone&#xff0c;无需使用 iTunes。您可以在这里获得更灵活、更人性化的备份…...

如何把 Mac Finder 用得更顺手?——高效文件管理定制指南

系统梳理提升 Mac Finder 体验的实用设置与技巧&#xff0c;助你用更高效的方式管理文件。文末引出进阶选择 Path Finder。 阅读原文请转到&#xff1a;https://jimmysong.io/blog/customize-finder-for-efficiency/ 作为一个用 Mac 多年的用户&#xff0c;我始终觉得 Finder 虽…...

赋能大型语言模型与外部世界交互——函数调用的崛起

大型语言模型 (LLM) 近年来在自然语言处理领域取得了革命性的进展&#xff0c;展现出强大的文本理解、生成和对话能力。然而&#xff0c;这些模型在与外部实时数据源和动态系统交互方面存在固有的局限性 1。它们主要依赖于训练阶段学习到的静态知识&#xff0c;难以直接访问和利…...

04 Deep learning神经网络编程基础 梯度下降 --吴恩达

梯度下降在深度学习的应用 梯度下降是优化神经网络参数的核心算法,通过迭代调整参数最小化损失函数。 核心公式 参数更新规则: θ t + 1 = θ t − η ∇ J ( θ...

手拉手处理RuoYi脚手架常见文问题

若依前后端分离版开发入门 基础环境&#xff1a;JDK1.8mysqlRedisMavenVue 取消登录验证码 后端 修改ruoyi-ui项目中的login.vue 在ruoyi-ui项目>src>views中找到login.vue文件 1、注释验证码展示及录入部分 2、 注释code必填校验&#xff0c;默认验证码开关为false …...

录制mp4

目录 单线程保存mp4 多线程保存mp4 rtsp ffmpeg录制mp4 单线程保存mp4 import cv2 import imageiocv2.namedWindow(photo, 0) # 0窗口大小可以任意拖动&#xff0c;1自适应 cv2.resizeWindow(photo, 1280, 720) url "rtsp://admin:aa123456192.168.1.64/h264/ch1/main…...

Dynamics 365 Finance + Power Automate 自动化凭证审核

&#x1f680; Dynamics 365 Finance Power Automate 自动化凭证审核 &#x1f4d1; 目录 &#x1f680; Dynamics 365 Finance Power Automate 自动化凭证审核1. 依赖 &#x1f527;2. 目标 &#x1f3af;3. 系统架构 &#x1f3d7;️4. 凭证审批全流程 &#x1f6e0;️4.1 …...

使用 Python + SQLAlchemy 创建知识库数据库(SQLite)—— 构建本地知识库系统的基础《一》

&#x1f4da; 使用 Python SQLAlchemy 创建知识库数据库&#xff08;SQLite&#xff09;—— 构建本地知识库系统的基础 &#x1f9e0; 一、前言 随着大模型技术的发展&#xff0c;越来越多的项目需要构建本地知识库系统来支持 RAG&#xff08;Retrieval-Augmented Generat…...

使用柏林噪声生成随机地图

简单介绍柏林噪声 柏林噪声&#xff08;Perlin Noise&#xff09;是一种由 Ken Perlin 在1983年提出的梯度噪声&#xff08;Gradient Noise&#xff09;算法&#xff0c;用于生成自然、连续的随机值。它被广泛用于计算机图形学中模拟自然现象&#xff08;如地形、云层、火焰等…...

P3 QT记事本(3.4)

3.4 文件选择对话框 QFileDialog 3.4.1 QFileDialog 开发流程 使用 QFileDialog 的基本步骤通常如下&#xff1a; 实例化 &#xff1a;首先&#xff0c;创建一个 QFileDialog 对象的实例。 QFileDialog qFileDialog;设置模式 &#xff1a;根据需要设置对话框的模式&…...

C++课设:实现简易文件加密工具(凯撒密码、异或加密、Base64编码)

名人说&#xff1a;路漫漫其修远兮&#xff0c;吾将上下而求索。—— 屈原《离骚》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 专栏介绍&#xff1a;《编程项目实战》 目录 一、初识文件加密&#xff1a;为什么需要…...

H_Prj06_03 8088单板机串口读取8088ROM复位内存

1.8088CPU复位时&#xff0c;CSFFFFH,IP0000H,因此在ROM的逻辑地址FFFF&#xff1a;0000&#xff08;FFF0H&#xff09;处一般要防止一个长跳转指令LJMP&#xff08;机器码位EAH&#xff09; 2.写一个完整的8086汇编程序&#xff0c;通过查询方式检测串口接收符串‘r’&#x…...

构建 MCP 服务器:第 3 部分 — 添加提示

这是我们构建 MCP 服务器的四部分教程的第三部分。在第一部分中&#xff0c;我们使用基本资源创建了第一个MCP 服务器&#xff1b;在第二部分中&#xff0c;我们添加了资源模板并改进了代码组织。现在&#xff0c;我们将进一步重构代码并添加提示功能。 什么是 MCP 提示&#…...

xcode 各版本真机调试包下载

下载地址 https://github.com/filsv/iOSDeviceSupport 使用方法&#xff1a; 添加到下面路径中&#xff0c;然后退出重启xcode /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport...

基于React + FastAPI + LangChain + 通义千问的智能医疗问答系统

&#x1f4cc; 文章摘要&#xff1a; 本文详细介绍了如何在前端通过 Fetch 实现与 FastAPI 后端的 流式响应通信&#xff0c;并支持图文多模态数据上传。通过构建 multipart/form-data 请求&#xff0c;配合 ReadableStream 实时读取 AI 回复内容&#xff0c;实现类似 ChatGPT…...

C# 中替换多层级数据的 Id 和 ParentId,保持主从或父子关系不变

在C#中替换多层级数据的Id和ParentId&#xff0c;同时保持父子关系不变&#xff0c;可以通过以下步骤实现&#xff1a; 创建旧Id到新Id的映射&#xff1a;遍历所有节点&#xff0c;为每个旧Id生成唯一的新Id&#xff0c;并存储在字典中。 替换节点的Id和ParentId&#xff1a;…...

Scade 语言概念 - 方程(equation)

在 Scade 6 程序中自定义算子(Operator)的定义、或数据流定义(data_def)的内容中&#xff0c;包含一种基本的语言结构&#xff1a;方程(equation)(注1)。在本篇中&#xff0c;将叙述 Scade 语言方程的文法形式&#xff0c;以及作用。 注1: 对 Scade 中的 equation, 或 equation…...

PG 分区表的缺陷

简介 好久没发文&#xff0c;是最近我实在不知道写点啥。随着国产化进程&#xff0c;很多 oracle 都在进行迁移&#xff0c;最近遇到了一个分区表迁移之后唯一性的问题。oracle 数据库中创建主键或者唯一索引&#xff0c;不需要引用分区键&#xff0c;但是 PG 就不行&#xff…...

从Copilot到Agent,AI Coding是如何进化的?

编程原本是一项具有一定门槛的技能&#xff0c;但借助 AI Coding 产品&#xff0c;新手也能写出可运行的代码&#xff0c;非专业人员如业务分析师、产品经理&#xff0c;也能在 AI 帮助下直接生成简单应用。 这一演变对软件产业产生了深远影响。当 AI 逐步参与代码生成、调试乃…...

Qt(part 2)1、Qwindow(菜单栏,工具栏,状态栏),铆接部件,核心部件 ,2、添加资源文件 3、对话框

1、Qwindow tips&#xff1a;1&#xff0c;首先为什么创建出的对象基本都是指针形式&#xff0c;个人觉得是对象树的原因&#xff08;自动释放内存&#xff09;&#xff0c;指针来访问成员函数->的形式。2&#xff0c;菜单栏只能一个的&#xff0c;放窗口基本Set&#xff0c…...

【图片识别Excel】批量提取图片中的文字,图片设置识别区域,识别后将文字提取并保存Excel表格,基于WPF和OCR识别的应用

应用场景 在办公自动化、文档处理、数据录入等场景中&#xff0c;经常需要从大量图片中提取文字信息。例如&#xff1a; 批量处理扫描的表单、合同、发票等文档从图片集中提取特定区域的文字数据将纸质资料快速转换为电子文本并整理归档 通过设置识别区域&#xff0c;可以精…...