Linux:“进度条”代码实现

1 \r和\n以及\r\n的区别

\r:将当前位置移到本行开头,又称为回车,对应键盘上的 return 键;

\n:将当前位置移到下一行,又称换行

不同操作系统,对于换行的理解是不一样的:Linux 中 \n 表示回车并换行;Windows 中 \r\n 表示回车并换行; Mac 中 \r 表示回车并换行。需要注意的是 C 语言中 \n 也表示回车并换行。

2 行缓冲区

#include <stdio.h>
#include <unistd.h>
  
int main()
{
     printf("hello linux!\n");
     sleep(3);
  
     return 0;
}

可以观察到的现象:“hello Linux!”语句立即打印出来,3 秒之后命令行刷新。

#include <stdio.h>
#include <unistd.h>
  
int main()
{
     printf("hello linux!");
     sleep(3);
  
     return 0;
}

去掉 \n 又是什么现象?可以观察到:“hello Linux!”语句不会立即打印出来,3 秒之后语句才打印出来,然后是命令行刷新在同一行。

#include <stdio.h>
#include <unistd.h>
  
int main()
{
     printf("hello linux!");
     fflush(stdout);
     sleep(3);
  
     return 0;
}

加一句 fflush(stdout); 代码又是什么现象?可以观察到:现象和第二个一样。

3 demo

#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define LENGTH 101
#define LABLE '#'

void Progress()
{
    const char* symb = "|/-\\";    // 光标
    int s_len = strlen(symb);
    char bar[LENGTH];
    //memset(bar, '\0', sizeof(bar) / sizeof(bar[0]);
    memset(bar, '\0', sizeof(bar));
    int cnt = 0;
    while(cnt <= 100)
    {   
        printf("[%-100s][%d%%][%c]\r", bar, cnt, symb[cnt % s_len]);
        fflush(stdout); // 刷新缓冲区
        bar[cnt++] = LABLE;
        usleep(50000);
    }   
    printf("\n");
}

int main()
{
    Progress();

    return 0;
}

4 进度条代码实现

// progress.h
#pragma once

#include <stdio.h>
#include <unistd.h>

void Progress();
void FlushProgress(double target, double current);

// progress.c

#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define LENGTH 101
#define LABLE '#'

void FlushProgress(double target, double current)
{
    // step 0: 定义光标
    const static char* sym = "|/-\\";
    static int index = 0;
    int len = strlen(sym);

    // step 2: 更新出进度
    double rate = (current / target) * 100.0;   // 5.0 100.0 -> 0.05 -> 5.0%
    // step 2: 整数个进度递增,刷新一个#
    int cnt = (int)rate;
    // step 3: 构建缓冲区
    char bar[LENGTH];
    memset(bar, 0, sizeof(bar));
    for(int i = 0; i < cnt; ++i)
    {
        bar[i] = LABLE;
    }
    // step 4: 刷新
    printf("[%-100s][%.1lf%%][%c]\r", bar, rate, sym[index++]);
    index %= len;
    fflush(stdout);
    // step 5: 处理更新到100%
    if(rate >= 100.0)
        printf("\n");
}
// main.c
#include "progress.h"

// 场景
double target_file_size = 1024.0;  // M,目标文件大小
double speed = 1.0; // M
    
void DownLoad(double size, double split)
{
    double current_total = 0.0;
    while(current_total <= size)
    {   
        FlushProgress(size, current_total);    // 进度条不能直接刷新完,需要根据具体的进度,来进行刷新
        if(current_total >= size) break;
        // 下载,用sleep来模拟
        usleep(10000); // 模拟一次下载时间
        current_total += split;
    }   
}

int main()
{
    printf("下载中:\n");
    DownLoad(target_file_size, speed);
    printf("下载中:\n");
    DownLoad(100.0, 1.0);
    printf("下载中:\n");
    DownLoad(512.0, 2.0);

    return 0;
}

# makefile
BIN=progress
CC=gcc
SRC=$(wildcard *.c)
OBJ=$(SRC:.c=.o)
LFLAGS=-o
CFLAGS=-c
RM=rm -f

$(BIN):$(OBJ)
    @$(CC) $(LFLAGS) $@ $^
    @echo "链接$^ 成为 $@"
%.o:%.c
    @$(CC) $(CFLAGS) $<
    @echo "编译$< 成为 $@"

.PHONY:clean
clean:
    @$(RM) $(OBJ) $(BIN)
    @echo "清理工程完毕"

执行效果图:

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值