📙 作者简介 :RO-BERRY
📗 学习方向:致力于C、C++、数据结构、TCP/IP、数据库等等一系列知识
📒 日后方向 : 偏向于CPP开发以及大数据方向,欢迎各位关注,谢谢各位的支持
目录
- 1.缓冲区
- 2)\n 和 \r
- 3.进度条
- ProgressBar.c
- ProgressBar.h
- Makefile
- main.c
1.缓冲区
-
第一种情况
执行结果如下:
可以看到程序先执行printf再执行sleep -
第二种情况
执行结果如下:
在这里为什么程序先执行sleep在执行printf呢?
实际上也并没有先执行sleep再执行printf,C语言执行代码是顺序结构自上往下
在这里运行的时候,程序运行sleep的时候printf早就运行完毕了
我们程序休眠之前没有看到字符串,那么我们输出的字符串一定是被保护起来了,在退出的时候才刷新出来
那么在sleep期间在哪里保存呢?
下面我们引出一个概念- - -缓冲区。
其实上面的现象中,在程序执行 printf 后,printf 打印的内容被存放到缓冲区中,在 C/C++ 中,会针对标准输出,给我们提供默认的缓冲区,而在缓冲区没有被刷新之前,我们的内容就不会被输出。
而 \n 就是一种刷新的策略 - - - 行刷新。所以我们加了 \n 后缓冲区被刷新,随即便打印出内容。
而我们没有使用 \n 的时候缓冲区并没有被刷新,但是我们可以使用 fflush(stdout) 强制刷新缓冲区,从而打印出内容,例如:
执行结果如下:
我们可以看到,缓冲区的内容被强制刷新出来了。
2)\n 和 \r
我们首先编写一个简单的倒计数程序,例如:
观察结果:
但是这并不是我们想要的倒计时,我们是期望在同一行中显示出来,所以我们不应该用 \n,其实 \n 就是我们所说的回车,就是使光标换行并回到那一行的最初位置;这时候我们就应该使用 \r,\r 就仅仅让光标回到当前行的最初位置,我们对上面的代码修改,如下:
执行结果如下:
从上面的结果可看出,我们的倒计时虽然在同一行了,但是输出的格式还是有问题,因为默认 %d 是按照一个字符的形式打印的,我们是要按照两个字符打印,所以我们仅需将%d修改为%2d即可,如下:
结果如下:
这时候就基本完成我们的倒计时了,但是倒计时到个位数的时候,前面空了一个字符,不太美观,这是因为 %2d 是默认右对齐,我们在前面加上负号,就是左对齐了,所以我们继续修改:
结果如下:
到此我们的倒计数就完成了。
3.进度条
ProgressBar.c
#include "ProgressBar.h"
const char *str = "|/-\\"; // 加载光标
void ProgressBar_v1()
{
// 当前进度
int rate = 0;
char bar[SIZE];
memset(bar, '\0', sizeof(bar));
// 加载光标的数组长度
int num = strlen(str);
// 当进度没有加载满
while(rate <= MAX_RATE)
{
printf("[%-100s][%d%%][%c]\r", bar, rate, str[rate % num]);
fflush(stdout);
usleep(STIME);
bar[rate++] = STYLE;
}
printf("\n");
}
ProgressBar.h
#include <stdio.h>
#include <unistd.h>
#include <string.h>
void ProgressBar_v1();
#define SIZE 101 //数组大小
#define MAX_RATE 100 //加载进度最大值
#define STYLE '#' //加载符号
#define STIME 1000*40 //时间
Makefile
ProgressBar:main.c ProgressBar.c
gcc -o $@ $^
.PHONY:clean
clean:
rm -f ProgressBar
main.c
#include "ProgressBar.h"
int main()
{
ProgressBar_v1();
return 0;
}
我们在使用延时函数的时候使用了 usleep 函数,它与 sleep 相比就是,sleep 中以 s 为单位;usleep 中以 us 为单位。
运行成果: