目录
1.知识补充
1.1回车和换行
1.2缓冲区
2.实现倒计时
3.实现进度条
1.知识补充
1.在制作小程序进度条之前,我们先了解一下,回车换行和行缓冲区的概念。
2.动态效果,在同一个位置刷新不同的图像,实现一个倒计时的效果。
3.有了上面的基础我们就可以实现进度条了
1.1回车和换行
所以说回车和换行是两个动作。
这是老式键盘。
在C语言中,\r表示的是只回车,\n表示的是只换行。
1.2缓冲区
看下面两段代码:
运行这个代码发现:printf打印的内容显示三秒后程序结束
运行这个代码发现:等待三秒后显示printf打印的内容程序结束
是因为下面子这段代码先执行sleep函数吗?当然不是,C语言的代码都是从上往下执行的,那为什么下面的代码是先暂停三秒然后才进行打印的呢?
这是因为在sleep期间,字符串进入了缓冲区。
缓冲区是计算机中用于临时存储数据的内存区域。在输入/输出操作中,数据通常不会立即传输到目的地,而是先存储在缓冲区中,以提高效率。缓冲区主要分为输入缓冲区和输出缓冲区:
1. **输入缓冲区**:用于存储从输入设备(如键盘、鼠标、文件等)读取的数据,直到程序准备处理这些数据。例如,当你输入文本时,字符会被存储在输入缓冲区中,直到程序读取并处理这些字符。
2. **输出缓冲区**:用于存储程序要发送到输出设备(如屏幕、打印机、文件等)的数据,直到达到一定条件时才会将数据发送到目的地。例如,当程序使用 printf 函数打印文本时,文本会先存储在输出缓冲区中,直到缓冲区满了、遇到换行符或调用 fflush 函数时才会将数据刷新到屏幕上。
在前面的例子中,由于 printf 函数打印的文本被存储在输出缓冲区中,而在调用 sleep(3) 函数之前并没有刷新缓冲区,所以你会看到在暂停3秒后才会将文本显示出来。这展示了缓冲区在程序执行过程中的作用。缓冲区的使用可以提高I/O操作的效率,但有时也需要注意缓冲区的刷新以避免数据延迟显示或丢失。
程序结束的时候,一般自动冲刷缓冲区。缓冲区满了也会进行刷新。
包含\n之前的字符会立即刷新。
还有一种情况,我既不想缓冲区满了才刷新,我也不想带\n进行刷新,该怎么办呢?
如果你想在不等待缓冲区满了或不使用换行符的情况下立即刷新输出缓冲区,你可以使用 fflush(stdout) 函数来手动刷新标准输出缓冲区。这样可以确保缓冲区中的内容立即被输出到屏幕上,而不必等待缓冲区满或遇到换行符。以下是一个示例代码:这个示例中, fflush(stdout) 函数用于手动刷新标准输出缓冲区,确保在暂停3秒之前将文本立即显示在屏幕上。这样你就可以在需要时控制何时刷新输出缓冲区,而不必等待缓冲区满或使用换行符。
2.实现倒计时
如何实现倒计时?
在同一个位置不断的刷新数字,如何做到?
输出一个数字,然后使用回车重新回到原来的位置(为了让数字变动的慢一些,我们设置sleep为1s,代码示例:
我们运行代码发现,什么数字都没有显示,程序10s后结束,这是因为出现在缓冲区还没有刷新就被覆盖掉了,所有我们要使用fflush函数刷新缓冲区
这样程序就有倒计时的效果了。
但如果是超过一个位数的这是就要控制回车移动的位置了:
eg:20s倒计时
3.实现进度条
准备工作:
第一个文件负责进度条功能的实现,第二个文件负责进度条功能的声明,第三个文件负责进度条的运行测试。Makefile负责进度条的自动化构建。
什么样的进度条:
我们在第一个位置预留100个字符的空间(显示进度条在增加),第二个位置显示进度,第三个位置有一个旋转的光标以表示在加载中。。。
首先定义一个char数组,memset全初始化为"\0",这时我们就一个一个的往数组中填写”#"
(间隔1s)表示进度条的增加
初步效果:确实在增加,但我们只需要他在一行中不断的打印
我们通过回车去覆盖,然后让缓冲区不断的刷新,这就有了只在一行中不断增加的效果
+、
我们在运行的过程中发现1s的间隔太慢,在这里我们将sleep函数换成(usleep)函数,间隔单位为微秒。(这里间隔换算为秒为:0.02s)
我们在显示的时候发现,进度条的框是随着进度的增加而变大的,这样的效果不太好看,因此我们直接预留100字符大小的框,这时我们再打印的时候就会发现框是有100个字符“#”的长度,但是进度条是从右往左增加的,这时因为字符默认是右对齐的,加上-变成左对齐。
这时候我们还可以在后面加上显示进度了百分之多少,在Linux中打印%,只需要输入连续的两个%:
最后我们将正在加载的效果显示出来:原理和倒计时一样,为了达到旋转的效果,我们将用几个方向的线顺序的出现来达到旋转的视觉效果
在这里模len是为了防止数组的越界
这时就有了旋转的效果了。
完整代码:
#include <unistd.h> #include <string.h> int main() { int i = 0; char bar[102]; memset(bar, 0, sizeof(bar)); const char* lable = "|/-\\"; while (i <= 100) { printf("[%-100s][%d%%][%c]\r", bar, i, lable[i % 4]); fflush(stdout); bar[i++] = '#'; usleep(10000); } printf("\n"); return 0; }