0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

教你在Linux上写一个进度条小程序

dyquk4xk2p3d 来源:入门小站 2023-01-29 11:37 次阅读

一、前言

Linux 上写下一个简易的进度条小程序。

成品展示

93c0b498-96c4-11ed-bfe3-dac502259ad0.gif

今天的内容比较轻松,只需要了解两个知识点,这个小程序就很容易写出来了,让我们开始今天的学习。

二、理解 ‘ ’ 与 ‘ ’

C 语言中有很多字符,而字符大体分为两类:可显字符、控制字符。

控制字符不可显示,例如 和 就是控制字符。

而在我们平时打字时,一行写满了需要换行,但是新起一行有很多种,例如:

93cdda7e-96c4-11ed-bfe3-dac502259ad0.png

这样虽然新起一行了,但是不是我们想要的结果。

我们通常新起一行是在第二行的最左端,但是对于这个结果其实有两个操作:

1.跳转到第二行

2.回到第二行的最左端

有了这个基本概念,再来谈 和 的作用:

:回车 - 回到文本行的开头

:换行 - 新起一行

所以,其实我们平时泛指的换行实际上是 回车 + 换行

且在语言范畴下,例如 C 语言,换行就可以达到回车 + 换行的效果。在平常,这一操作还是两个步骤。

三、行缓冲

行缓冲这个概念认识。

1、提出问题

首先先了解一下两个库函数:

sleep:Linux 下的休眠函数,单位是秒。头文件为#include

fflush:刷新缓冲区

代码 1:

#include
intmain()
{
printf("helloxxx");
sleep(3);
return0;
}

现象:

93e6f360-96c4-11ed-bfe3-dac502259ad0.gif

分析:

光标停留在文本行的开头,但是字符串没有被打印。

反而像是 sleep 函数先起作用,然后 printf 函数再从光标处开始打印。

打印完之后,shell 提示符紧跟着字符串后显示。

代码 2:

#include
intmain()
{
printf("helloxxx
");
sleep(3);
return0;
}

现象:

93f45a50-96c4-11ed-bfe3-dac502259ad0.gif

分析:

printf 打印的字符串先显示在终端上,光标位于字符串的下一行。

sleep 函数使程序休眠 3 秒后,shell 提示符从光标位置开始显示。

代码 3:

#include
intmain()
{
printf("helloxxx
");
sleep(3);
return0;
}

现象:

93fc5f3e-96c4-11ed-bfe3-dac502259ad0.gif

分析:

printf 打印的字符串没有显示到终端,光标一直停留在该打印字符串的一行

sleep 函数休眠三秒后,shell 提示符直接打印在了屏幕上。并没有看到字符串。

观察上面的现象,我们提出几个问题:

代码 1 好像是先执行了 sleep ,在执行 printf ,是这样吗?

代码 2 加上了 ‘ ’ ,字符串一开始就显示了,为什么?

代码 3 好像什么都没打印,这是为什么?

在解答这些问题之后,我们先了解一下行缓冲。

2、认识行缓冲

在内存中预留了一块空间,用来缓冲输入或输出的数据,这个保留的空间被称为缓冲区。

我们之前或多或少都听说过缓冲区。

在代码 1 中,由于程序是按照数据执行的,所以必定是先执行 printf 。

但是数据没有显示,所以这时候,数据就一定被保存在某个位置,保存的位置就是缓冲区。

而要让数据显示,是需要刷新缓冲区的。

行缓冲是缓冲区刷新策略的一种,在行缓冲模式下,当输入和输出中遇到 ‘ ’ 换行时,就会刷新缓冲区

有了这个概念,我们继续分析问题。

3、解答与拓展

解答

问题 1:代码 1 好像是先执行了 sleep ,在执行 printf ,是这样吗?

当然不是。由于程序是按照顺序执行的,所以必定是先执行完 printf 在执行 sleep 。

而数据没有被显示出来的原因是:数据保存在缓冲区中,但是没有主动刷新,当程序退出后,保存在缓冲区中的数据被自动刷新出来了。

所以才会造成这种现象。

问题 2:代码 2 加上了 ,字符串一开始就显示了,为什么?

这里由于是直接往显示器上打印,所以采用的刷新方式为行缓冲。

所以执行碰到 ‘ ’ 时,就会把在缓冲区中的 (换行符之前) 的内容全部刷新出来。

所以这段代码一开始就会有数据显示,然后再 sleep 休眠。

问题 3:代码 3 好像什么都没打印,这是为什么?

之前说过 是换行,所以当 printf 遇到 时,就把光标移到开头。sleep 睡眠后,当程序退出,shell 打印提示符时,就覆盖了字符串。

拓展

数据真的是临时保留在缓冲区里的吗?光标如何理解?

我们用一段代码来理解这两个问题:

#include
#include
intmain()
{
printf("helloxxx
");
fflush(stdout);
sleep(3);
return0;
}

现象:

94037e36-96c4-11ed-bfe3-dac502259ad0.gif

观察现象,我们发现当我们使用fflush主动刷新缓冲区后,数据就显示在了屏幕上;且因为 ‘ ’ 的原因,光标指向字符串开头;当打印 shell 提示符时,就直接从光标位置开始覆盖。

所以对于这两个问题,我们已经得到了答案:

1.数据被临时保存在于缓冲区中,通过刷新就可以显示

2.数据是从光标位置开始打印的。

一句话理解光标:光标和显示器匹配,光标在哪里,显示器打印的时候就从哪里开始打印

4、倒计时

基于对上面的理解,我们先实现一个简单的倒计时。

倒计时就是在屏幕上不断显示数字,每次在同一位置显示,并将之前的数据覆盖。

既然是每次要从头开始覆盖,那么就可以用 ‘ ’ 来实现每次回到行首,并且可以通过相应的格式化控制显示多位打印。

但是 ‘ ’ 不会主动刷新,所以要用fflush函数主动刷新缓冲区。

在每次刷新之后,使用 sleep 函数,间隔一定的时间。

由此,我们可以很轻松写出代码,例如写一个从 10 开始的倒计时:

#include
#include

intmain()
{
inti=10;
for(;i>=0;i--){
//位宽控制,
回到开头
printf("%2d
",i);
fflush(stdout);//主动刷新
sleep(1);//休眠
}
printf("
");//换行,打印提示符
return0;
}
94115808-96c4-11ed-bfe3-dac502259ad0.gif

四、进度条

好了,接下来进入正题,我们开始写进度条

进度条样式

主体样式为两个中括号包裹,中间=>推进的方式呈现,比如:[======>]

主体右侧中括号位置保持不变,中间元素不断推进,比如:[=> ]

显示当前加载进度,用[num%]显示,num 随着进度条的不断推进而变化

显示加载样式,可以利用一个旋转的字符,例如[]的样式,顺时针不断旋转

大约呈现状态为:[========>] [15%] []

采用多文件

文件存放在proc目录中

proc.h :函数声明

proc.c :进度条逻辑

main.c :函数调用

makefile准备

由于采用多文件,所以依赖关系可以写成依赖文件列表的样式:

941a4648-96c4-11ed-bfe3-dac502259ad0.png

分块逻辑

1.进度条主体

预留进度条大小为 100 个=,外加 1 个>,加上保存'�'的位置,用数组存储为 102 个单位。

进度条是一行中的,所以需要用到' ',每次都需要使用fllush主动刷新缓冲区。

每次刷新出数据之后,将 = 填充到数组中,并且显示 > 。在最后一次显示时,控制 > 不要显示。

然后休眠一小会。由于休眠用 sleep 函数太慢。所以可以用 usleep 函数休眠,usleep 函数的参数单位是微秒。

根据这个写出代码:

942199a2-96c4-11ed-bfe3-dac502259ad0.png942b83a4-96c4-11ed-bfe3-dac502259ad0.gif

2.百分比显示

%% 显示为一个 % ,而 %d 为数字,这步很简单,只要在 printf 语句中加上内容:

printf("[%-100s][%d%%]
",bar,i);

3.旋转光标

光标旋转方向为顺时针旋转,那么旋转时就可以用数组保存。

旋转每次显示内容分别为| / - ,\代表一个 ,因为和 结合的会被解析为转义字符,将其保存到字符串中。

而由于字符串一共就四个字符,所以输出的时候需要控制输出位置。

代码:

constchar*str="|/-";//字符串
printf("[%-100s][%d%%][%c]
",bar,i,str[i%4]);//输出语句

完整代码

proc.h

#pragmaonce

#include

externvoidprocess();

proc.c

#include"proc.h"
#include
#include

#defineSIZE102//数组大小
#defineSTYLE'='
#defineFLAG'>'

voidprocess()
{
constchar*str="|/-";
charbar[SIZE];
memset(bar,'�',sizeof(bar));
inti=0;
while(i<= 100) {
      printf("[%-100s][%d%%][%c]
", bar, i, str[i % 4]); // 格式控制
      fflush(stdout); // 刷新
      bar[i++] = STYLE; // 填充数据
      if (i != 100) {
          bar[i] = FLAG; // 如果不是最后一次则显示 >
}
usleep(100000);//休眠
}
printf("
");
}

test.c

#include"proc.h"

intmain()
{
process();
return0;
}

进度条展示

93c0b498-96c4-11ed-bfe3-dac502259ad0.gif

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    87

    文章

    11292

    浏览量

    209332
  • C语言
    +关注

    关注

    180

    文章

    7604

    浏览量

    136694
  • 字符
    +关注

    关注

    0

    文章

    233

    浏览量

    25199
  • 函数
    +关注

    关注

    3

    文章

    4327

    浏览量

    62573
  • 小程序
    +关注

    关注

    1

    文章

    234

    浏览量

    12126

原文标题:教你在 Linux 上写一个进度条小程序

文章出处:【微信号:良许Linux,微信公众号:良许Linux】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    关于进度条

    我用的labview8.6,初学者,在那能找到进度条啊!
    发表于 10-28 11:35

    如何在程序中加进度条显示程序运行的进度

    由于数据很大,程序运行的时间很长,想在程序中加进度条显示程序运行的
    发表于 08-14 22:30

    如何为运行得很慢的程序添加进度条或者任何提示?

    问题是:该程序的循环底层VI中,该VI用户不可更改。较顶层的程序均不存在循环。为了排解等待程序运行过程中的无聊,想加个进度条,或者任何会动
    发表于 09-26 16:59

    请问怎么用进度条显示程序进度

    怎么用进度条显示程序进度
    发表于 12-24 10:02

    如何显示vi程序运行的进度条

    程序调用mtalab脚本节点,运行很慢,想设计进度条,实时显示运行进度,求各位大神帮忙
    发表于 04-01 13:53

    labview的进度条

    这是labview的进度条程序,比较好用
    发表于 08-04 14:30

    labview进度条

    我用labview2017做了文件解压和复制的vi,解压过程中不知道真实的解压进度,怎么才能做一个真实的进度条,要真是的,不是自己规定的
    发表于 04-26 09:10

    为什么烧不了程序,进度条直不动?

    怎么烧不了程序...进度条直不动啊...
    发表于 07-18 05:45

    怎么设置进度条

    RT!比如 我创建随意长度的进度条然后我知道文件的大小 当把这个文件里的数据读完后进度条
    发表于 08-22 04:35

    如果更新太快,进度条对象无法正确呈现?

    嗨,所有,我正在更新和谐进度条对象的基础定时器值。如果我使用的时间小于1500毫秒,进度条对象背景和边框不能正确渲染。这段视频更清楚地
    发表于 09-20 06:18

    HarmonyOS实战——ProgressBar进度条组件基本使用

    ProgressBar案例——点击进度条增加实际进度值需求分析:每单击进度条组件时,进度条就加 5% 的
    发表于 09-22 23:31

    Linux下实现进度条程序,通过makefile进行编译

    1. Linux下实现进度条程序。 通过makefile进行编译。 建议自主完成彩色的
    发表于 03-12 16:31 2113次阅读

    Linux基础教程之linux wget下载进度条变成多行显示如何解决

    之前为了 解决Putty客户端连接到CentOS之后显示乱码 的问题,设置了 LANG=zh_CN.UTF-8 之后,使用wget下载的时候,wget下载进度条异常,竟然不能在
    发表于 10-31 17:04 19次下载

    如何利用ChatGPT快速实现控制台进度条小工具?

    控制台程序执行些耗时任务时,需要向用户显示当前任务执行的进度,以提供清晰的感知。比如下载程序
    的头像 发表于 01-18 13:41 917次阅读
    如何利用ChatGPT快速实现<b class='flag-5'>一</b><b class='flag-5'>个</b>控制台<b class='flag-5'>进度条</b>小工具?

    【AWTK使用经验】如何设计立体电池进度条

    AWTK是基于C语言开发的跨平台GUI框架。《AWTK使用经验》系列文章将介绍开发AWTK过程中些常见问题与解决方案,例如:如何加载外部资源?如何设计自定义进度条?这些都会在系列文章进行解答
    的头像 发表于 04-18 08:25 451次阅读
    【AWTK使用经验】如何设计立体电池<b class='flag-5'>进度条</b>?