当前位置:   article > 正文

linux入门---制作进度条_printf打印进度条

printf打印进度条

了解缓冲区

我们首先来看看下面的操作:
在这里插入图片描述
我们首先创建了一个文件并在这个文件里面添加了一些代码,代码的内容就是首先打印一段话然后再休眠几秒,在命令行中输入一个make生成了一个可执行程序,我们将这个可执行程序运行一下就可以看到出现了这样的现象:
在这里插入图片描述
运行这个可执行程序之后没有打印任何的内容,但是过了3秒钟之后屏幕上又显示了我们要打印的内容
在这里插入图片描述
那这是为什么呢?sleep函数的功能确实是休眠对应的秒数,但也应该是先在屏幕上打印出来内容再休眠啊!那么要想知道这里的原因我们就得提到一个概念叫做缓冲区,对于这段代码我们首先可以确定的一点就是printf语句一定是在sleep函数之前执行的,既然这个printf语句被执行了那么他就一定会把数据打印出来放到一个位置,而这里的屏幕上没有对应的数据,那么这就说明printf函数没有将内容打印到屏幕上而是放到了缓冲区里面,之所以过了3秒钟屏幕上显示了对应的内容是因为我们的程序结束了,当一个程序结束的时候操作系统会刷新缓冲区,这样屏幕上才会显示我们要打印的内容。这里是程序结束的时候操作系统刷新的缓冲区,而printf语句给了一个操作可以让我们人为的刷新缓冲区就是在printf里面添加\n,比如说下面的操作:
在这里插入图片描述
我们再make一下并运行可执行程序就可以看到这里先打印了内容在这里插入图片描述
再休眠了一段时间在这里插入图片描述
那么这就是\n的作用,他可以将缓冲区中的内容刷新并输出到应该输出的地方。

\n和\r

我们知道\n的作用是回车换行并刷新缓冲区,那么这里\r的作用就是回车但不会刷新缓冲区,回车换行这个东西大家应该都不陌生,他可以让输出位置来到下一行的最左边,而回车的作用是将输出位置移动到当前行的最左边,比如说下面的代码:
在这里插入图片描述
我们将这段代码运行一下就可以看到这里打印的内容有三行:
在这里插入图片描述
那这里就有个问题\r不会刷新缓冲区那我们怎么来打印呢?方法也很简单可以调用fflush函数,并将stdout作为参数传给这个函数,这样每次运行的时候就可以将缓冲区的内容输出到屏幕上,使用这个函数需要包含头文件unistd.h我们来看看下面的代码:
在这里插入图片描述
在代码的结尾之所以要打印一个\n是为了防止输出的内容被命令提示行给覆盖了,那么这段代码的运行结果如下:
在这里插入图片描述
我们可以看到这里输出的内容只有一行,而回车换行输出的内容却有三行,那之所以出现这样的原因就是因为:输出到显示器上的内容就像泼出去的水,一旦跑到显示器上去了就不会动了,这里的回车是让输出位置来到当前行的最左边,此时再输出内容只会覆盖掉原来的内容,不会将原来的内容往后挪动再输出内容,所以这里没有出现三行内容,也没有出现一行有多个内容的现象,那看到这里我们是不是就可以根据这个现象来写一个简单的倒计时程序就好比从10倒计时到1,那么这个程序实现的方法就是先定义一个变量a将其值赋值为10,然后创建一个循环在循环里面通过printf加\r加fflush的方式将变量a的值打印出来,并且每次循环都将a的值减去1并且休眠1秒,那么这里的代码实现就如下:
在这里插入图片描述
我们将这段代码运行一下,发现是可以正常运行的:
在这里插入图片描述
但是除第10秒其他秒的位置好像发现了错位,那这是为什么呢?

在这里插入图片描述
我们将程序修改一下让其只输出数字不输出文字看看会是一个什么样的结果:
在这里插入图片描述
将其运行一下就会发现一开始打印的内容是10但是后来打印的内容就是90 80 70 60…
在这里插入图片描述
那这是为什么呢?原因很简单我们之前说过往显示器上输入内容是不能动的,只会被后来的数据给覆盖,而我们之前输入的数据是10,占了屏幕上的两个位置,但是后来我们往屏幕上输出的内容只占一个位置,所以就只会覆盖最左边的数据,不会覆盖第二个,所以第一次我们看到的内容是10,第二次就变成了90,那么要想解决这个问题我们就得让每次刷新的数据个数是相等的,这里就可以在%d的d前面加上对应的数字,其作用是每次刷新屏幕上的n个数据,这里最多是2个字符所以把%d改成%2d,然后再运行一下就可以看到这里的结果是没有问题的:
在这里插入图片描述
在这里插入图片描述
我们将之前的文字描述也添加上去,再运行一下就可以看到这里不会发生错位:
在这里插入图片描述
那么看到这里想必大家应该能够理解这里的回车和回车换行的用法,那么我们接着往下看。

进度条的制作

有了上面的基础我们再来制作一个进度条就会变得非常的容易,我们在看电影看电视剧下载东西的时候经常会看到进度条,那么这个进度条他是会随着时间的流逝在慢慢变长,而这里的变长我们可以将其进行简化,比如说第一秒打印一个#,第二秒就打印两个,第三秒就打印三个,就这么一直这么循环下去知道时间达到了一定的长度。但是这里我们要注意的一点就是这里的变长不是累加,所以我们每次打印内容之后都要用\r来进行换行并且使用sleep函数将其程序休眠一下来表示时间那么这就是我们进度条的大致思路。好首先创建四个文件main.c process.h process.c,makefile。其中process.c是源文件,process.h是头文件,main.c是包含主函数的文件。我们使用vim打卡main.c这个文件,在这个文件里面先包含头文件process.h,再写好main函数,在main函数里面调用proncesson函数,这个函数在源文件里面定义,那么这里的操作就如下:
在这里插入图片描述

在这里插入图片描述

然后我们就在底行模式下使用vs指令打开头文件:
在头文件里面引用stdio.h文件,和对proncesson函数进行声明:
在这里插入图片描述
然后我们就保存并退出头文件,然后再打开源文件,在源文件里面完成函数的定义,那么这里我们先在该函数里面输出一句话,用来测试我们以上的步骤以及接下来makefile中的操作是否正确:
在这里插入图片描述

然后我们就将所有的文件都保存退出并打开makefile文件,这里在写makefile的时候就有个问题,原来写的makefile所生成得到可执行程序只依赖一个文件,但是以这样的写法来生成可执行程序的时候好像会依赖三个文件,那这里该怎么写呢?方法也很简单,虽然我们这里写了三个文件,但是在makefile中写依赖文件的时候只需要写两个文件上去:main.c和process.c,写依赖方法的时候也是用gcc对这两个文件同时编译,不同的文件用空格将其隔开,那么这里的操作就如下:
在这里插入图片描述
那这里就有小伙伴会问,那这里的头文件不需要包含吗?答案是在makefile当中是不需要包含头文件的,因为头文件就在当前的路径下,你的编译器能够找到头文件在哪,大家记住只要你的头文件和源文件在同一个目录下,那么你写makefile的时候就不要把头文件写上去,编译器会自动在当前路径下进行查找,我们之前讲过头文件的查找有两个路径一个是当前路径一个就是库路径,那这里的找就是编译器在找,我们把makefile的clean写完运行一下看看这里能不能执行成功:
在这里插入图片描述
在命令行中输入make,并运行一下可执行程序就可以看到这里确实打印出来了内容:
在这里插入图片描述
那么这就说明我们之前写的三个文件和makefile文件之间的联系是真确的,接下来我们就来实现真正的proncesson函数,首先我们得知道一件事就是进度条一定是通过循环来实现的,所首先得创建一个while循环进度条是从0%增加到100%,所以这里循环次数为101次,那这里的代码就如下:
在这里插入图片描述
我们说进度条的底层原理是第一次打印一个字符,第二次就将光标移动到当前行的开头再打印两个字符,第三次就是将光标移动到当前行的开头然后再打印三个字符,我们把上面的操作放到循环里面,并且每次循环我们都让程序休眠一段时间,这样我们看到的现象就是一个个连续的字符随着时间在不停的变长,因为这里要不停的打印多个字符串,所以这里就可以创建一个字符数组,因为要循环101次所以就把数组的大小设为101,并将数组中的内容全部都初始化为\0,那么这里的操作就如下:
在这里插入图片描述
因为这里用到了memset函数,所以得在头文件中包含string.h头文件,数组创建完之后就得在循环里面输出字符数组中的内容,这里的打印就得用到printf函数和\r和fflush函数,并且每次打印完我们都得往数组里面多添加一个字符,这里的添加字符就可以使用下标引用加cnt值的方式,添加完之后就使用sleep函数休眠一段时间,再通过循环我们就可以打印一个简版的进度条,那么这里的操作就如下:
在这里插入图片描述
保存并退出运行一下这里的文件就可以看到屏幕上打印出来了下面的内容:
在这里插入图片描述
我们可以看到屏幕上面打印出来了一个缓慢的进度条你,但是这里的打印有点慢影响我们的观察,我们就可以把这里的sleep修改成usleep,sleep函数是休眠对应的秒数,那么usleep函数就是休眠对应的微秒数,我们给usleep函数传个50000,这样我们的进度条就可以在5秒内跑完:
在这里插入图片描述
将其运行一下就可以看到此时的打印速度快了很多,但是我们发现这里打印的进度条在命令行提示符的后面:
在这里插入图片描述
如果我们想要让命令行和进度条分离的话就得在函数的末尾添加一个\n上去
在这里插入图片描述
但是这样打印出来的进度条不是非常的美观,所以我们可以在进度条的两端添加一个括号上去,并且这个括号不随里面内容长度的改变而发生变化,所以我们得在s的前面添加一些数字来预留一定的空间,并且数据的打印是从右往左的所以我们得在数字的前面加上一个负号,这样我们数据的打印就变成了从左往右,那么这里的操作就如下:
在这里插入图片描述

我们将上面的代码运行一下就可以看到此时的进度条的形式变成了这样:
在这里插入图片描述
但是我们平时看到的进度都是会带百分比的,所以在括号的后面再加上一个括号,并且在括号的里面输入百分比,这里大家要注意的一点就是printf中打印%的形式是%%,所以这里代码修改的形式就是这样:
在这里插入图片描述
运行一下就可以看到这里出现了进度条的百分比:
在这里插入图片描述
我们平时看到的进度条还有个圆圈在不停的转动来表示此时的进度条正在不停的加载,那么这里就可以再创建一个数组,并且数组里面的内容为这四个字符:| / - \,当进度条不停的加载时cnt的值就在不停的增加,所以我们就可以根据cnt%4的值作为这个数组的下标来不停的打印数组的内容,这样不停的打印时就可以看到一个旋转的圆圈,那么这里的代码如下:
在这里插入图片描述
这段代码的运行结果如下:
在这里插入图片描述
有时候我们不想使用这种形式的进度条,想把#改成>的话我们这里就可以再创建一个数组,这个数组里面装着不同的风格的进度条,这样我们就可以通过定义不同宏N的值来达到不同的形式,那么这里的操作就是这样:
在这里插入图片描述
更改makefile中的内容在依赖方法中定义一个宏N并将其值赋值为1,我们就可以看到此时进度条的形式变成了这样:
在这里插入图片描述
在这里插入图片描述
那么这就是这篇文章的全部内容希望大家能够理解。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/313021?site
推荐阅读
相关标签
  

闽ICP备14008679号