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

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

文章目录

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


Linux第一个小程序-进度条

相关知识

特殊符号:

$@$^

回车换行:

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

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

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

缓冲区:


创建程序

1. 程序原理

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

90fba84f0e0005c99c57ff6c2367442b

然后创建3个文件

3d4f2bd15e379210a78b12b490666269

然后进入processBar.h,写一下

877c447368658d92654537194d4eb6c0

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

c331c2e83fc18a04d7e652db18560d93

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

processbar:processBar.c main.c
        gcc -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");//1

        sleep(2);             //2
        return 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");//1
        fflush(stdout); // 强制刷新标准输出缓冲区
        sleep(2);             //2
        return 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);             //2
        return 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);             //2
        return 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);             //2
        return 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);             //2
        return 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; //1000MB
    int curr = 0; //0MB
    while(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.kler.cn/a/503436.html

相关文章:

  • 【Uniapp-Vue3】showLoading加载和showModal模态框示例
  • 蓝牙BT04-A的使用与相关AT指令
  • 【微服务】面试题 5、分布式系统理论:CAP 与 BASE 详解
  • 【学习路线】Python自动化运维 详细知识点学习路径(附学习资源)
  • Pandas常用数据类型
  • 【Python进阶——分布式计算框架pyspark】
  • Ubuntu安装K8S
  • 【Uniapp-Vue3】组件中emit的声明触发事件
  • 华为数通-访问控制列表
  • 网络安全的几种攻击方法
  • 【数据仓库】— 5分钟浅谈数据仓库(适合新手)从理论到实践
  • IOday6互斥和同步
  • 《拉依达的嵌入式\驱动面试宝典》—操作系统篇(七)
  • 完全二叉树的顺序存储【堆】
  • [c#] 度分秒和度的转换
  • 轨迹优化 | 基于贝塞尔曲线的无约束路径平滑与粗轨迹生成(附ROS C++/Python仿真)
  • 嵌入式系统中的 OpenCV 与 OpenGLES 协同应用
  • 【C】初阶数据结构3 -- 单链表
  • maven高级(day15)
  • 安装虚拟机VMware遇到的问题
  • JAVA安全编码规范
  • 七 rk3568 android 11 ec20 4G驱动移植
  • EasyControl:首个登陆AWS Marketplace的中国MDM先锋
  • electron 上怎么用node 调用 c++ 提供的方法
  • 深度学习模型适应两种不同的正态分布
  • STM32 FreeRTOS移植