Linux小程序:进度条

目录

一、换行与回车

二、缓冲区

三、倒计时代码

四、进度条实现


实现进度条程序,首先需要两个预备知识:

1.换行与回车

2.缓存区

一、换行与回车

我们通常使用\n作为换行符,但实际上\n是换行+回车两种效果的结合,因此我们需要区分一下换行与回车的区别:

换行是从上一行的第n个位置跳转到下一行的第n个位置;回车则是从某一行的第n个位置跳转到该行的第一个位置

\r表示回车,\r\n表示回车+换行(只有\n和\r一起使用时,\n才表示换行),\n表示回车+换行

二、缓冲区

先对比两段代码,唯一的区别就是printf函数输出时有没有加上\n

运行时,代码1会先输出内容,再等待3秒;代码2会先等待3秒,再输出内容

由此引入问题:代码2先等待3秒,但是程序运行时一定是按顺序执行代码,也就是说是printf函数先执行,那么再等待的这3秒内,printf函数输出的数据在哪里呢?

答案是:在缓冲区,printf输出的数据会被拷贝到缓冲区,在程序运行结束的时候会冲刷缓冲区,此时printf输出的数据才会显示出来

cpp 复制代码
//第一段代码
#include <stdio.h>
#include <unistd.h>
int main()
{
   printf("hello makefile\n");
   sleep(3);                                                                                                       
   return 0;
}

//第二段代码
#include <stdio.h>
#include <unistd.h>
int main()
{
   printf("hello makefile");
   sleep(3);                                                                                                       
   return 0;
}

缓冲区的三种冲刷方式:

(1)\n冲刷

printf输出时加上\n,printf输出的数据被拷贝到缓冲区,\n会自动冲刷缓冲区

(2)fflush强制冲刷

我们可以调用fflush函数强制冲刷缓冲区,包含在头文件<unistd.h>

(3)程序运行结束冲刷

程序运行结束时,也会自动冲刷缓冲区

三、倒计时代码

根据上面的理解,我们可以实现一个简单的倒计时代码

C语言在输出时会默认打开3个标准输入输出流,分别为stdin、stdout、stderr,其中stdin为键盘输入,stdout和stderr都是显示器输出

cpp 复制代码
#include <stdio.h>
#include <unistd.h>
int main()
{
   int cnt=9;
   while(cnt>=0)
   {                                                                             
     printf("倒计时:%d\r",cnt);                     
     fflush(stdout);              
     sleep(1);                                                                                                     
     cnt--;                                     
   }                                  
   printf("\n");//最后一行\n的作用是防止程序最后的输出倒计时:0 被命令行提示符覆盖
                //因为\r回车,光标回到了倒计时:0的前面,此时再输出命令行提示符一定会覆盖倒计时:0
                //而使用\n换行后,缓冲区的光标就会跳到 倒计时:0 的下一行,此时输出命令行提示符就不会覆盖倒计时:0
   return 0;                             
}      

如果cnt初始值为10,则始终有一个0无法被覆盖,此时我们需要将%d改为%2d,使得输出字段的最小宽度为2,小于2则在左侧用空格补齐,这样就能覆盖掉0了

cpp 复制代码
#include <stdio.h>
#include <unistd.h>
int main()
{
   int cnt=10;
   while(cnt>=0)
   {                                                                             
     printf("倒计时:%2d\r",cnt);                     
     fflush(stdout);              
     sleep(1);                                                                                                     
     cnt--;                                     
   }                                  
   printf("\n");
   return 0;                             
}      

四、进度条实现

cpp 复制代码
//progress_bar.h
void progress_bar();

//progress_bar.c
#include <stdio.h>
#include "progress_bar.h"
#include <memory.h>
#include <unistd.h>
#define out '#'
void progress_bar()
{
    char rotate[4] = {'|', '/', '\\', '-'};
    char arr[101];
    memset(arr, '\0', 101);
    int cnt = 0;
    while (cnt < 100)
    {
        arr[cnt] = out;
        printf("[%-100s][%d%%][%c]\r", arr, cnt + 1, rotate[cnt % 4]);
        fflush(stdout);
        usleep(20000); // usleep,单位为微秒
        cnt++;
    }
    printf("\n");
}

//main.c
#include <stdio.h>
#include "progress_bar.h"
int main()
{
    progress_bar();
    return 0;
}
相关推荐
2035去旅行9 小时前
bootcmd 详细讲解
linux·嵌入式·arm·soc
陈希12310 小时前
Linux 防火墙配置实战:firewalld、iptables 与云安全组
linux·运维·服务器
女神下凡11 小时前
芯参谋(95):嵌入式文件系统_开发指南
linux·服务器·arm开发·驱动开发·设计规范
且从容.14 小时前
Ubuntu安装flume
linux·ubuntu·flume
承渊政道15 小时前
Linux网络学习【Reactor反应堆模式】
linux·网络·学习·ubuntu·reactor
且从容.18 小时前
ubuntu安装flink
linux·ubuntu·flink
爱和冰阔落19 小时前
【Linux网络】TCP 服务器如何并发处理多个客户端?从 fork、僵尸进程到双重 fork
linux·运维·服务器·网络
程序员沉梦听雨19 小时前
WSL2的安装与使用
linux·wsl
微小的鱼19 小时前
Linux的渲染与显示系统链路
android·java·linux
lisanmengmeng20 小时前
alertmanger 标签 rules 打上分组标签
linux·运维·服务器