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;
}
相关推荐
爱瑞瑞27 分钟前
🐧深入浅出的认识 Linux 指令
linux·shell
ajassi200041 分钟前
开源 java android app 开发(十一)调试、发布
android·java·linux·开源
小李飞刀李寻欢1 小时前
使用kubeadm部署Kubernetes(k8s)集群的步骤
linux·服务器·ubuntu·kubernetes·k8s
运维成长记1 小时前
阿里云实践创建实例步骤
linux·运维·服务器·阿里云·云计算
THe CHallEnge of THe BrAve2 小时前
Linux检验库是否安装成功
linux·运维·服务器
算家计算2 小时前
告别复杂文档解析噩梦!MonkeyOCR 本地部署教程:支持公式/表格多元素结构化
linux·人工智能·开源
曹勖之3 小时前
ROS2 工作空间中, CMakeLists.txt, setup.py和 package.xml的作用分别是?
xml·linux·服务器·ros2
企鹅侠客4 小时前
ttyd:安全地通过网络共享您的 Linux 终端
linux·运维·ttyd
饭碗、碗碗香4 小时前
【开发常用命令】:服务器与本地之间的数据传输
linux·运维·服务器·笔记·学习
MonkeyBananas5 小时前
在Ubuntu中使用Apache2部署项目
linux·运维·ubuntu