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

文章目录


Linux第一个小程序-进度条

相关知识

特殊符号:

$@$^
回车换行:

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

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

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


创建程序

1. 程序原理

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

然后创建3个文件

然后进入processBar.h,写一下

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

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

bash 复制代码
processbar:processBar.c main.c
        gcc -o $@ $^
.PHONY:clean
clean:
        rm -f processbar

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

c 复制代码
# include "processBar.h"
#include <unistd.h>

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

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

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

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

c 复制代码
# include "processBar.h"
#include <unistd.h>

int main()
{
        printf("hello world");//1

        sleep(2);             //2
        return 0;
}

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

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

当然不是。

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

那为什么会这样呢?

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

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

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

如果我要强制刷新呢?

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

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

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文件,更改一下代码:

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;
}

得到:

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

我们加个\r就可以了

c 复制代码
# 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;
}

打印:

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

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

c 复制代码
# 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一次打印两个字符,而且是左对齐。

bash 复制代码
# 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

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

c 复制代码
#pragma once
  
#include <stdio.h>

#define NUM 102
#define STYLE '#'

extern void processbar();

main.c

c 复制代码
# include "processBar.h"
#include <unistd.h>

int main()
{
    processbar();
    return 0;
}

实现效果:


箭头进度条代码实现

processBar.c

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

c 复制代码
#pragma once
  
#include <stdio.h>

#define NUM 102
#define STYLE '-'

extern void processbar();

main.c

c 复制代码
# include "processBar.h"
#include <unistd.h>

int main()
{
    processbar();
    return 0;
}

实现效果:


多重进度条代码实现

processBar.c

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

c 复制代码
#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

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;
}

实现效果:

相关推荐
学习编程的gas几秒前
Linux基本指令(三)
linux·运维·服务器
mrbone114 分钟前
Linux-linux和windows创建新进程的区别以及posix_spawn
linux·运维·windows·多进程·fork
u0109053596 分钟前
内网穿透之Linux版客户端安装(神卓互联)
linux·运维·服务器
conkl1 小时前
Kali Linux 安全工具解析
linux·网络·安全·kali
JAVA和人工智能1 小时前
linux 安装 canal 的详细步骤
linux·运维·服务器
三脚猫的喵2 小时前
微信小程序实现运动能耗计算
javascript·微信小程序·小程序
风筝超冷2 小时前
通过模型文件估算模型参数量大小
linux·服务器
deeper_wind2 小时前
防火墙设置实战操作案例(小白的“升级打怪”成长之路)
linux·运维·网络
huangyuchi.2 小时前
【Linux】自动化构建-Make/Makefile
linux·运维·服务器·笔记·自动化·makefile·make