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

实现效果:

相关推荐
Christal_pyy12 分钟前
树莓派4基于Debian GNU/Linux 12 (Bookworm)添加多个静态ipv4网络
linux·网络·debian
csbDD1 小时前
2025年网络安全(黑客技术)三个月自学手册
linux·网络·python·安全·web安全
李狗蛋儿啊1 小时前
zero自动化框架搭建---Git安装详解
运维·git·自动化
小金的学习笔记2 小时前
如何在本地和服务器新建mysql用户和密码
运维·服务器·mysql
s_fox_2 小时前
nginx ngx_http_module(7) 指令详解
运维·nginx·http
EasyNVR2 小时前
EasyRTC智能硬件:实时畅联、沉浸互动、消音护航
运维·服务器·网络·安全·音视频·webrtc·p2p
CarryBest3 小时前
Jenkins 环境搭建---基于 Docker
运维·jenkins
若云止水3 小时前
Ubuntu 下 nginx-1.24.0 源码分析 - ngx_process_options
运维·nginx
s_fox_3 小时前
nginx ngx_http_module(9) 指令详解
运维·nginx·http
Natsuagin3 小时前
轻松美化双系统启动界面与同步时间设置(Windows + Ubuntu)
linux·windows·ubuntu·grub