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

ops/2025/1/15 23:33:23/

文章目录

  • Linux第一个小程序-进度条
    • 相关知识
    • 创建程序
      • 1. 程序原理
      • 2. 基础程序原理实现
    • 井号进度条代码实现
    • 箭头进度条代码实现
    • 多重进度条代码实现


Linux第一个小程序-进度条

相关知识

特殊符号:

$@$^

回车换行:

回车和换行其实是两个东西。

回车:挪到下一行的最前面。

换行:挪到下一行的当前位置,就是从上往下。

缓冲区:


创建程序

1. 程序原理

我们先创建一个文件夹,进去

90fba84f0e0005c99c57ff6c2367442b

然后创建3个文件

3d4f2bd15e379210a78b12b490666269

然后进入processBar.h,写一下

877c447368658d92654537194d4eb6c0

然后往main.c里面写一点东西。

c331c2e83fc18a04d7e652db18560d93

然后创建makefile文件,进去编写代码

processbar:processBar.c main.cgcc -o $@ $^
.PHONY:clean
clean:rm -f processbar

然后进入main.c,修改代码

# include "processBar.h"
#include <unistd.h>int main()
{printf("hello world\n");sleep(2);//这个要用到unistd.h头文件return 0;
}

现象是先打印hello world,然后休眠2s

12b5ff537a50e0491b6f7cf95a198c2e

然后进入main.c,修改代码,去掉\n,那么现象会是什么呢?

是先打印hello world,然后休眠2s还是先休眠2s,然后打印hello world呢?

# include "processBar.h"
#include <unistd.h>int main()
{printf("hello world");//1sleep(2);             //2return 0;
}

得到的现象是先休眠2s,然后打印hello world

eb201771774b8b54f0d77dee2e50e78b

咦,怎么会这样?难道先执行了第二条语句,然后执行第一条语句吗?

当然不是。

C语言是按顺序执行的,所以执行顺序一定是先执行第一条语句,再执行第二条语句。

那为什么会这样呢?

sleep期间,printf语句执行完了,那么它在这两秒内怎么了呢?

因为后面还是打印出来了,说明printf一定被保存起来了。

保存在了C语言的缓冲区,这个缓冲区就是指由C语言维护的一段内存。

如果我要强制刷新呢?

C语言文件默认打开3个文件:标准输入流,标准输出流(显示器显示),标准错误流

我们继续更改一下main.c文件,添加一行代码:

# include "processBar.h"
#include <unistd.h>int main()
{printf("hello world");//1fflush(stdout); // 强制刷新标准输出缓冲区sleep(2);             //2return 0;
}

再次运行的结果就不一样了,现象是先打印hello world,然后休眠2s

关键点解释:

  1. printf("hello world");

    • 将字符串输出到标准输出
    • 但由于缓冲机制,不一定立即显示在屏幕上
    • 内容可能暂存在缓冲区中
  2. fflush(stdout);

    • 强制刷新标准输出缓冲区
    • 确保"hello world"立即显示在屏幕上
    • 不使用fflush时,内容可能要等到缓冲区满或程序结束才显示
  3. sleep(2);

    • 让程序暂停执行2秒
    • 单位是秒
    • 这期间程序什么都不做

如果去掉fflush(stdout)

  • "hello world"可能要等到程序结束才显示
  • 因为程序很快就结束了,用户可能看不到2秒暂停的效果

2. 基础程序原理实现

好的 ,通过上面的原理,应该都知道了缓冲区的存在了。

比如我们输入一个9,那么光标就跑到9的后面了。

我们在9的前面输入一个8,那么9就被挤到8的后面了,得到了89

我们进入main.c文件,更改一下代码:

# include "processBar.h"
#include <unistd.h>int main()
{//倒计时int cnt = 9;while(cnt){printf("%d",cnt);fflush(stdout);cnt--;sleep(2);}//printf("hello world");//1//fflush(stdout);//sleep(2);             //2return 0;
}

得到:

b07e42583ece2d6294df12f83d6dd4d9

43cbffbaa39a4330624b2044569c5818

4a2b6f1abb1bf292c2d637de58fa8baa

但是这个不是让光标回到最开始写的,怎么修改呢?

我们加个\r就可以了

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

打印:

b60153092e70e314bb16095bb84aef14

1e48f466b5808fb11869c7574bd5be01

实现了一个简单的倒计时。

不过表面上看起来我们实现的很完美,可是如果倒计时变成两位数的话:

# include "processBar.h"
#include <unistd.h>int main()
{//倒计时int cnt = 10;while(cnt>=0){printf("%d\r",cnt);fflush(stdout);cnt--;sleep(2);}printf("\n");//printf("hello world");//1//fflush(stdout);//sleep(2);             //2return 0;
}

程序打印为:

10 --> 90 -->80。。。

因为打印的是字符。

这里我们只需要加一个-2就可以了,%-2d一次打印两个字符,而且是左对齐。

# include "processBar.h"
#include <unistd.h>int main()
{//倒计时int cnt = 10;while(cnt>=0){printf("%-2d\r",cnt);fflush(stdout);cnt--;sleep(2);}printf("\n");//printf("hello world");//1//fflush(stdout);//sleep(2);             //2return 0;
}

井号进度条代码实现

processBar.c

#include "processBar.h"
#include <string.h>
#include <unistd.h>const char *lable="|/-\\";void processbar()
{char bar[NUM];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(100000);}printf("\n");
}

processBar.h

#pragma once#include <stdio.h>#define NUM 102
#define STYLE '#'extern void processbar();

main.c

# include "processBar.h"
#include <unistd.h>int main()
{processbar();return 0;
}

实现效果:

cf69253f3299694ed79d6a0caec61cd9

0d0d1dfdd1fc78db8474f7ebb2dabf52


箭头进度条代码实现

processBar.c

#include "processBar.h"
#include <string.h>
#include <unistd.h>const char *lable="|/-\\";void processbar()
{char bar[NUM];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;if(cnt <=100) bar[cnt]='>';usleep(100000);}printf("\n");
}

processBar.h

#pragma once#include <stdio.h>#define NUM 102
#define STYLE '-'extern void processbar();

main.c

# include "processBar.h"
#include <unistd.h>int main()
{processbar();return 0;
}

实现效果:

c367f606a7fdc1c1eff71e0dafbac6fa

dc95e546ea847928c22b61ae746bf5de


多重进度条代码实现

processBar.c

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

processBar.h

#pragma once#include <stdio.h>#define NUM 102
#define TOP 100
#define BODY '='
#define RIGHT '>'extern void processbar(int rate);
extern void initbar();

main.c

# include "processBar.h"
#include <unistd.h>typedef void (*callback_t)(int);void downLoad(callback_t cd)
{int total = 1000; //1000MBint curr = 0; //0MBwhile(curr <= total){usleep(50000);int rate=curr*100/total;cd(rate);curr+=10;}printf("\n");
}int main()
{printf("download 1: \n");downLoad(processbar);initbar();printf("download 2: \n");downLoad(processbar);initbar();printf("download 3: \n");downLoad(processbar);initbar();printf("download 4: \n");downLoad(processbar);initbar();return 0;
}

实现效果:

9008f42d031aa83f7ab402b845b4914c


http://www.ppmy.cn/ops/150413.html

相关文章

STM32程序发生异常崩溃时,怎样从串口输出当时的程序调用栈等信息

当STM32程序发生异常崩溃时&#xff0c;为了从串口输出当时的程序调用栈信息&#xff0c;并使用Keil等工具确定具体的函数信息&#xff0c;你可以按照以下步骤操作&#xff1a; 启用调试信息输出&#xff1a; 在STM32程序中&#xff0c;你需要先确保启用了调试信息的输出。这通…

微信小程序-Docker+Nginx环境配置业务域名验证文件

在实际开发或运维工作中&#xff0c;我们时常需要在 Nginx 部署的服务器上提供一个特定的静态文件&#xff0c;用于域名验证或第三方平台验证。若此时使用 Docker 容器部署了 Nginx&#xff0c;就需要将该验证文件正确地映射&#xff08;挂载&#xff09;到容器中&#xff0c;并…

iOS - Objective-C语言的动态性

Objective-C 的动态性主要由以下几个关键特性和机制支撑&#xff1a; 1. 动态消息传递 // 消息传递机制 id objc_msgSend(id self, SEL _cmd, ...) {// 1. 获取类信息Class cls object_getClass(self);// 2. 查找方法实现IMP imp lookUpImpOrForward(cls, _cmd);// 3. 执行…

ip属地出省会变吗?怎么出省让ip属地不变

在数字化时代&#xff0c;IP属地作为网络身份的一个重要标识&#xff0c;不仅影响着我们的网络体验&#xff0c;还与网络安全、隐私保护等方面息息相关。当我们跨省移动时&#xff0c;是否会遇到IP属地变化的问题&#xff1f;如果希望保持IP属地不变&#xff0c;又该如何操作呢…

linux 网络安全不完全笔记

一、安装Centos 二、Linux网络网络环境设置 a.配置linux与客户机相连通 b.配置linux上网 三、Yum详解 yum 的基本操作 a.使用 yum 安装新软件 yum install –y Software b.使用 yum 更新软件 yum update –y Software c.使用 yum 移除软件 yum remove –y Software d.使用 yum …

用css和html制作太极图

目录 css相关参数介绍 边距 边框 伪元素选择器 太极图案例实现、 代码 效果 css相关参数介绍 边距 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><style>*{margin: 0;padding: 0;}div{width: …

Web前端------HTML多媒体标签之图片标签

一.图片标签介绍 1.路径问题>.绝对路径从盘符开始的路径问题&#xff1a;改变了工程目录的位置后&#xff0c;绝对路径从盘符开始则不能使用了&#xff0c;考虑相对路径>.相对路径从当前位置&#xff08;指从代码书写.html文件&#xff09;开始如何表示当前位置------使用…

强化风险防控:助贷 CRM 系统为助贷中介筑牢安全堤坝

对于助贷中介公司而言&#xff0c;风险防控无疑是关系到生死存亡的关键环节。在复杂多变的市场环境下&#xff0c;传统的风险管控手段漏洞百出&#xff0c;而助贷 CRM 系统的出现&#xff0c;为筑牢安全堤坝提供了坚实保障。 贷前审查阶段&#xff0c;公司以往仅能通过有限的资…