【Linux从入门到精通】C语言模拟实现进度条小程序

简介: 在Linux下,我们安装软件时会经常看到进度条,来告知我们安装的进度。我们不妨自己模拟实现一个进度条,看看其中的细节。模拟实现进度条并不困难,但其中的细节我们又不可忽视。本篇文章会对模拟实现进度条进行详解。

 在Linux下,我们安装软件时会经常看到进度条,来告知我们安装的进度。我们不妨自己模拟实现一个进度条,看看其中的细节。模拟实现进度条并不困难,但其中的细节我们又不可忽视。本篇文章会对模拟实现进度条进行详解



一、进度条整体模板


 谈到进度条,我们首先想到的是一个动态表示进度的显示程序。 首先,我们先来看一下进度条整体的模板,也就是我们所要模拟实现的进度条。如下:

模板1:

模板2:

 我们看到,上述有两个模板,两个模板大同小异,只是输出格式不同而已。我们似乎已经有了一个大概的整体思路。无非就是格式打印输出嘛。真的是这样吗?确实是这样。但并不只是单纯的输入和输入。其中还涉及到了缓冲区和回车、换行的概念和细节。我们接着往下看。


二、输出缓冲区详解

 我们平常使用的printf函数,是输出到屏幕。但是是直接输出到屏幕的吗?我们看下面的例子:

#include<stdio.h>      
int main()    
{    
  int i=0;    
  for(i=5;i>=0;i--)                                                                                                                                          
  {    
    printf("%d",i);      
    sleep(1);  //睡眠1秒
  }    
  return 0;    
}



我们看上述代码,输出结果是什么呢?我们第一反应是每间隔一秒依次输出5、4、3、2、1、0。我们直接看结果:

 我们看到并非每间隔一秒依次输出5、4、3、2、1、0。而是过了6秒后直接输出了5、4、3、2、1、0。这是为什么呢?从这例子,我们间接了解到输出并非直接输出到屏幕上。那中间还有什么呢?其实,我们输出是先输出到了缓冲区。缓冲区又分为输入缓冲区和输出缓冲区。这里明显的是先输出到了输出缓冲区。

9f4085e448f44437b320edd4887764e8.png


我们再看一个例子:

#include<stdio.h>      
int main()    
{    
  int i=0;    
  for(i=5;i>=0;i--)                                                                                                                                          
  {    
    printf("%d\n",i);       
    sleep(1);  //睡眠1秒
  }    
  return 0;    
}



上面的代码相对于第一个例子,我们多了一个换行。我们再看一下输出结果:

 我们看到是每间隔一秒依次输出5、4、3、2、1、0。这又是为什么呢?这就关系到了把输出缓冲区的内容刷新到屏幕上的规则:


程序正常结束,作为main函数return操作的一部分,缓冲区被刷新。

当缓冲区的内容满了的时候,缓冲区会自动刷新到屏幕上。

可以使用操作符endl、fflush和 ends 来显示的刷新缓冲区。这三个都是IO库中的操作符,endl能完成换行和刷新缓冲区的工作。flush只完成刷新缓冲区的工作。而ends会向缓冲区插入一个空字符,然后刷新缓冲区。

 了解到了输出缓冲区的刷新规则后,我们对上面的两个例子的输出结果就很容易理解了。当然,我们讲解了这么多输出缓冲区是为什呢?我们先回到模拟实现进度条,我们打印的进度条,是在一行上打印出的,并没有换行。这里就引出了两个问题:怎么做到不换行还能不断动态更新打印数据呢?怎么及时打印出缓冲区的数据呢?我们接着往下看。


三、模拟实现进度条思路及代码详解

3、1 回车和换行区别



我们上面的问题是:怎么做到不换行还能不断动态更新打印数据呢?首先换行( \ n )是不可以的。这里我们就可以用回车( \ r )。啊???换行和回车不一样吗?答案是不一样的。


 回车 \r 本义是光标重新回到本行开头,r的英文return,控制字符可以写成CR,即Carriage Return。


 换行 \n 本义是光标往下一行(不一定到下一行行首,还有可能是接上一行 行末另起一行。),n的英文newline,控制字符可以写成LF,即Line Feed。


 但是回车并不能刷新缓冲区。所以我们还要用到fflush(stdout)来刷新缓冲区到屏幕上。我们可结合下面例子一起理解一下:

#include<stdio.h>    
#include<unistd.h>    
int main()    
{    
  int i=0;    
  for(i=5;i>=0;i--)    
  {    
    printf("%d\r",i);                                                                                                                                        
    fflush(stdout);    
    sleep(1);    
  }    
  return 0;    
} 


 通过不断的在同一行输出,我们可以得到一个类似倒计时的小程序,具体输出结果如下:

 通过上面的例子,我们可以很好的理解回车和换行的区别。同时又解决了上述的两个问题。



3、2 模拟实现进度条思路详解

3、2、1 初阶进度条


首先,我们想到的是进度条完成是达到百分之百。那我们可以定义一个长度为105字符数组,这里多5个位置,是为了防止越界造成不必要的麻烦(注意,打印字符串时遇到‘\0’停止)。我们可通过100次循环,不断改变字符数组内容,再同过回车(\r)和格式化输出,我们就可以得到一个初步形式的进度条。我们结合代码一起理解:

#include<stdio.h>    
#include<unistd.h>    
#include<string.h>    
#define MAX 105    
int main()    
{    
  int i=0;    
  char bar[MAX];    
  memset(bar,0,sizeof(bar));   //初始化字符数组为0
  while(i<=100)    
  {    
    printf("[%-100s][%3d%%] \r",bar,i,);     
    fflush(stdout);    
    bar[i]='#';    
    i++;    
    usleep(50000);    
  }    
  printf("\n");    
  return 0;     
}   


上面我们可以看到有usleep函数。sleep函数睡眠时间是以秒为级别的。usleep是以微妙级别的。usleep(50000)也就是睡眠0.05秒。循环100次一共是睡眠5秒,也就是我们5秒多一点可以完成打印整个进度条。我们看输出结果:

3、2、2 进阶进度条


我们为了表示进度条在运行,我们可在最后加上一个旋转的字符表示正在运行。怎么加一个旋转的字符呢?我们可创建一个字符数组,存储旋转字符的不同状态。进而通过循环来控制字符旋转。我们可看如下代码:

#include<stdio.h>    
#include<unistd.h>    
#include<string.h>    
#define MAX 100    
int main()    
{    
  int i=0;    
  char bar[MAX+5];    
  memset(bar,0,sizeof(bar));    
  const char* arr="|\\-/";    //旋转字符数组
  while(i<=100)    
  {    
    printf("[%-100s][%3d%%] %c\r",bar,i,arr[i%4]);                                                                                                           
    fflush(stdout);                                                                                                                     
    bar[i]='#';
    //bar[i] = '-';
    //bar[i+1] = '>';     //另一种格式                                                                                       
    i++;                                                                                                                                
    usleep(50000);                                                                                                                      
  }                                                                                                                                     
  printf("\n");                                                                                                                         
  return 0;                                                                                                                             
}


我们直接看输出结果:


d2f1680b1f2c4630a90afe6a1c1462b7.gif


 最后会有一个动态表示的字符。这样看起来就会比较完整。当然,输出的格式我们可以自己选择。输出的颜色也可通过查询添加到自己的输入格式当中。


 以上就是整个用C语言实现的进度条。其中有很多细节还是比较重要的,需要我们重点掌握。希望本篇文章会对你有所帮助,感谢观看ovo~  

相关文章
|
1月前
|
安全 编译器 C语言
C++入门1——从C语言到C++的过渡
C++入门1——从C语言到C++的过渡
47 2
|
2天前
|
Unix Linux Shell
linux入门!
本文档介绍了Linux系统入门的基础知识,包括操作系统概述、CentOS系统的安装与远程连接、文件操作、目录结构、用户和用户组管理、权限管理、Shell基础、输入输出、压缩打包、文件传输、软件安装、文件查找、进程管理、定时任务和服务管理等内容。重点讲解了常见的命令和操作技巧,帮助初学者快速掌握Linux系统的基本使用方法。
16 3
|
2月前
|
机器学习/深度学习 安全 网络协议
Linux防火墙iptables命令管理入门
本文介绍了关于Linux防火墙iptables命令管理入门的教程,涵盖了iptables的基本概念、语法格式、常用参数、基础查询操作以及链和规则管理等内容。
219 73
|
30天前
|
机器学习/深度学习 Linux 编译器
Linux入门3——vim的简单使用
Linux入门3——vim的简单使用
54 1
|
1月前
|
存储 Java 编译器
初识C语言1——C语言入门介绍
初识C语言1——C语言入门介绍
27 1
|
30天前
|
Linux Shell Windows
Linux入门1——初识Linux指令
Linux入门1——初识Linux指令
25 0
Linux入门1——初识Linux指令
|
26天前
|
C语言
回溯入门题,数据所有排列方式(c语言)
回溯入门题,数据所有排列方式(c语言)
|
27天前
|
存储 数据可视化 Linux
Linux 基础入门
Linux 基础入门
|
30天前
|
Linux Go 数据安全/隐私保护
Linux入门2——初识Linux权限
Linux入门2——初识Linux权限
24 0
|
2月前
|
Shell Linux API
C语言在linux环境下执行终端命令
本文介绍了在Linux环境下使用C语言执行终端命令的方法。首先,文章描述了`system()`函数,其可以直接执行shell命令并返回结果。接着介绍了更强大的`popen()`函数,它允许程序与命令行命令交互,并详细说明了如何使用此函数及其配套的`pclose()`函数。此外,还讲解了`fork()`和`exec`系列函数,前者创建新进程,后者替换当前进程执行文件。最后,对比了`system()`与`exec`系列函数的区别,并针对不同场景推荐了合适的函数选择。