当前位置: 首页 > news >正文

Linux小程序(1)—— 简单进度条

本文记录在Linux中实现一个简单进度条程序。要完成此程序,需要用到前置知识;需要掌握vim的基础操作和Linux自动化构建工具makefile的使用。详细请查看文章:Linux(4)—— 基础开发工具

 项目框架

进度条程序我们很熟悉,在手机电脑上玩游戏、下载安装软件等我们都能看到下方会有一个安装后加载的进度条。在开始该程序项目之前,我们需要理清楚设计的框架。

首先,要有main函数文件,即main.c文件。

然后,要有一个头文件,我们创建一个名为processBar.h的头文件。此外,程序的主要实现代码也可以单独放在一个文件里。我们再创建一个processBar.c的文件用于存放程序主要逻辑代码。

最后,运用我们前面学习到的Linux自动化项目构建工具 makefile(Makefile),我们需要再创建一个makefile文件。

综上所述,我们一共需要创建四个文件,自己选择一个适合的文件夹,创建上面的四个文件:\

touch main.c processBar.h processBar.c Makefile

创建好之后,我们打开头文件加入库:

#pragma once#include <stdio.h>

之后我们再打开Makefile进行配置:

processbar:pricessBar.c main.cgcc -o $@ $^
.PHONY:clean
clean:rm -f processbar

这样我们输入make指令就会生成processbar的程序,需要清除项目使用make clean即可。

我们来看一下Makefile里面的代码。

可以看到我们编译和清理一个名为processbar的程序。第一行为依赖关系;文件proceeBar.c和main.c两个文件时目标文件的依赖项,即processbar依赖于这两个源文件。

第二行 gcc -o $@ $ 是构建目标的命令。其中 $@是Makefile自动变量,代表目标文件名(即processbar)。而$^代表所有依赖文件,即(processBar.c 和 main.c源文件)

所以第二行的依赖方法等效于下面的代码:

gcc -o processbar processBar.c main.c

最后,.PHONY:clean:表示声明 clean 是一个伪目标:

伪目标不对应实际的文件,总是执行其命令防止目录中存在名为 clean 的文件时规则不执行。

最后的删除代码我们在 Linux(4)—— 基础开发工具 中有过演示,这里不再说明。

倒计时

在正式开始进度条程序之前,我们先来尝试设计部一个倒计时程序。这样方便我们理解构建项目。如果不想完成这部分,可以直接点击目录跳转到进度条项目。

下面我们创建一个 test.c 文件进行编写。

#include "processBar.h"int main()
{return 0;
}

1、打印数字

要看到倒计时,首先我们肯定要能看的到倒计时的数字。我们假设一共需要倒计时9秒钟。

#include "processBar.h"int main()
{int cnt = 9;while(cnt>=0){printf("%d",cnt);cnt--;}return 0;
}

编译后运行看一下,发现成功打印:

2、模拟时间

但是我们发现这是一下子全部打印出来了,所以我们需要模拟一下时间,让程序一秒钟打印一个数字;这里我们使用sleep。在Linux中,sleep的参数单位是秒,这和windows系统不同。

#include "processBar.h"int main()
{int cnt = 9;while(cnt>=0){printf("%d",cnt);fflush(stdut);//刷新打印cnt--;sleep(1);//间隔一秒}return 0;
}

我们再次运行就能成功看到每隔一秒打印一个数字了。

3、覆盖

不过倒计时并不会全部把数字显示出来;我们如何实现只看到一个数字?这就需要将前面已经打印的内容进行覆盖。前面我们在打印的时候是顺着后面打印的,因为光标出现在打印的数字后面。要想实现覆盖,就需要实现打印时的光标出现在打印的数字左边(前面)。我们这里使用\r,表示将光标移动到当前行的开头。这样我们就能成功实现覆盖操作。

#include "processBar.h"int main()
{int cnt = 9;while(cnt>=0){printf("%d\r",cnt);//使用/r将光标移动到当前行开头实现覆盖fflush(stdut);//刷新打印cnt--;sleep(1);//间隔一秒}return 0;
}

我们也可以加上在最后打印一个换行符(看着更舒服):

#include "processBar.h"int main()
{int cnt = 9;while(cnt>=0){printf("%d\r",cnt);fflush(stdut);//刷新打印cnt--;sleep(1);//间隔一秒}printf("\n");return 0;
}

4、打印两位数

如果我们需要倒计时的时间为两位数,我们将cnt的值改为10,再次运行看一下:

这个时候问题出现了,10的第二位0会一直保持在屏幕上。要解决这个问题,只需要做出如下改动:

#include "processBar.h"int main()
{int cnt = 10;while(cnt>=0){printf("%2d\r",cnt);fflush(stdut);//刷新打印cnt--;sleep(1);//间隔一秒}printf("\n");return 0;
}

我们将%d改为了%2d,这样表示按至少2个字符宽度输出整数。因为10开始是表示两个字符,它不是我们看到的10 ,而是一个1和一个0。所以我们使用%2d就可以打印两个字符,实现二位数的倒计时。以此类推,三位数,甚至四位数倒计时也可以实现。不过一般情况不会显示那么大的数字。

不过,还可以改进一点。我们发现按照上面的运行之后,打印的数字会停留在第二个字符位置。所以我们再改成 %-2d,让打印的数字进行左对齐,运行后发现没有问题。

#include "processBar.h"int main()
{int cnt = 10;while(cnt>=0){printf("%-2d\r",cnt);fflush(stdut);//刷新打印cnt--;sleep(1);//间隔一秒}printf("\n");return 0;
}

这样我们就成功实现了倒计时。

进度条

1、准备工作

下面我们打算在processbar函数里面进行主要功能的代码实现。所以我们需要在processbar.h文件中对该函数进行声明,在process.c文件中写入主要代码;最后要在main.c文件中实现调用。

所以在头文件中:

#pragma once#include <stdio.h>extern void processbar();

声明一个processbar函数。

在processBar.c文件中,先写好processbar函数;这里为了方便测试,我们先在函数中写一个打印语句:

#include "processBar.h"void processbar()
{printf("Hello processBar!\n");
}

最后在main函数中进行对processbar函数的调用:

#include "processBar.h"int main()
{processbar();return 0;
}

关于makefile文件的配置我们不做修改。

下面我们make一下,看能否正常运行:

一切正常。

下面我们直接实现processbar函数即可。

2、函数实现

我们可以将进度条分成100份,用字符来表示进度,每一个字符表示%1;在后面进度增加的时候,将光标移动到当前字符的左边,用新的字符将前面的覆盖,实现递增效果。

所以我们需要一个数组来存储这些字符内容,并通过循环来实现打印。

我们先定义进度条打印的字符,假设为#,设置数组的大小为102;打开头文件:

#pragma once#include <stdio.h>
#include <string.h>
#include <unistd.h>#define NUM 102
#define STYLE '#'//进度条字符extern void processbar();

打开函数文件,我们先使用while循环打印数组:

#include "processBar.h"void processbar()
{char bar[NUM];memset(bar,'\0',sizeof(bar))//初始化数组int cnt = 0;while(cnt <= 100){printf("%s\n",bar);//打印字符串bar[cnt++] = STYLE;sleep(1);//模拟间隔}
}

这里我们先用\n换行符查看一下是否实现增加。

make后运行一下,可以看到现在会一行一行地增加字符:

下面我们需要让其实现覆盖。

和前面的倒计时一样,我们需要使用\r来实现光标跳转。此外,还需要进行刷新。

\n为换行,光标跳转到开头并刷新,而\r是只跳转光标。没有\n,就没有立即刷新,因为显示模式是行刷新方式。所以我们还需要使用fflush刷新。

#include "processBar.h"void processbar()
{char bar[NUM];memset(bar,'\0',sizeof(bar))//初始化数组int cnt = 0;while(cnt <= 100){printf("%s\r",bar);//打印字符串fflush(stdout);//刷新 bar[cnt++] = STYLE;sleep(1);//模拟间隔}
}

我们再次运行就发现可以正常覆盖了。

3、usleep

我们发现一秒钟打印一个字符似乎有点太慢了,要观察程序到结束要耗时一分多钟。因此我们将sleep换成usleep可以让程序运行时间缩短。

usleep和sleep都是进行休眠。只不过usleep的参数单位是微秒。我们设置时间间隔为0.1秒,而进制关系为:1 s = 1000000微秒。

所以我们修改一下代码:

#include "processBar.h"void processbar()
{char bar[NUM];memset(bar,'\0',sizeof(bar))//初始化数组int cnt = 0;while(cnt <= 100){printf("%s\r",bar);//打印字符串fflush(stdout);//刷新 bar[cnt++] = STYLE;usleep(100000);//模拟间隔}
}

4、预留空白

我们为整个进度条加上[]框:

#include "processBar.h"void processbar()
{char bar[NUM];memset(bar,'\0',sizeof(bar));//初始化数组int cnt = 0;while(cnt<=100){printf("[%-100s]\r",bar);fflush(stdout);bar[cnt++] = STYLE;usleep(100000);}printf("\n");
}

加上-号表示左对齐。

5、显示百分比

除了字符显示进度,我们还需要设置一个百分比的数字显示。

#include "processBar.h"void processbar()
{char bar[NUM];memset(bar,'\0',sizeof(bar));//初始化数组int cnt = 0;while(cnt<=100){printf("[%-100s][%d%%]\r",bar,cnt);//%%表示%号fflush(stdout);bar[cnt++] = STYLE;usleep(100000);}printf("\n");
}

上面的进度条我们使用的是#来做加载字符;我们也可以改变风格,使用其他的字符来展示。例如=号或-号等等。

http://www.dtcms.com/a/615402.html

相关文章:

  • 做gif图的网站优质外贸网站
  • 网上虚拟银行注册网站店铺logo在线制作免费
  • 东莞装饰网站建设蛟河市建设局网站
  • 第一章 函数与极限 8.函数的连续性与间断点
  • Day3算法训练(简写单词,dd爱框框,3-除2!)
  • Edu144 CD
  • 不同数据结构在硬件平台(如ARM、x86)上的性能表现差异
  • 无限容量网站wordpress新用户提醒
  • 网站欢迎页面flash兰州公司网站建设
  • 岚图泰山将登陆欧洲、中东,岚图泰山的海外布局如何看?
  • 广州网站设计工作室芜湖网站建设whwzjs
  • 网页设计新建站点数字广东网络建设公司
  • 做搬家广告哪家网站有优百度指数怎么看排名
  • 网站系统后台网站建设销售提点20个点
  • 做学历的网站建e网下载
  • 如何来做网站优化网站开发维护求职信
  • 淮北市住房和城乡建设局网站如何韩国视频网站模板下载 迅雷下载地址
  • 网站建设sunmun网站建设方面的书籍推荐
  • 龙港 网站建设一站式网络营销
  • 专业网站制作咨询大丰网站建设价格
  • AI营销与销售专家咨询顾问培训讲师培训师唐兴通分享GEO优化白皮书
  • 个人小程序为企业做网站建设优化小程序包年竞价
  • 做分类信息网站如何wordpress网站文件管理
  • python做网站服务器购物型网站用dw做
  • 【贪心 图论】517. 超级洗衣机|分数未知
  • php网站开发个人网络营销渠道的类型有哪些
  • Java 基于分支和循环结构的专项实验
  • 电商网站建设与维护网站添加多个关键词
  • 网站虚拟主机有什么用唐山网站建设400多少钱
  • 住房和城乡建设部网站中国建造师网西安网络推广网站优化