在进行进度条的程序的编写之前,还有几个问题需要解决。
第一个问题,先来看两段代码:
对比上面两段代码只有一个\n
的区别。
左边的代码很简单,就是先打印,然后停顿 3 秒,程序退出。
主要问题是,右边的代码,也实先打印,然后停顿 3 秒,程序退出吗?
答案显然不是。真实看到的运行结果是,程序先停顿了 3 秒,然后打印输出完之后,程序直接退出。
至于为什么,当然是缓冲区的问题了。
根据程序从上到下顺序执行的规则,其实printf
语句是比sleep
先执行的,只是信息没有被立即打印出来罢了。
没有被及时打印出来的信息被送入缓冲区,而显示器设备的刷新策略一般都采用的是行刷新(碰到换行符刷新),所以信息就被“逗留”在了缓冲区。然后程序停顿 3 秒,退出程序的时候缓冲区的信息又被刷新到屏幕上。就好像出现了程序并没有按顺序执行的情况。
这里可以用fflush
这个函数进行验证。fflush
可以将文件缓冲区进行刷新。
第二个问题,什么是换行?什么是回车?
换行就是换到当前位置的下一行,回车就是回到当前行的起始位置。
程序中,\n
表示换行,\r
表示回车。
但是程序中的换行\n
通常都做了特殊处理,好像是换行和回车的结合体。
最后进入进度条程序的编写(Vim)。
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define NUM 52
int main()
{
char bar[NUM] = {0};
int count = 1;
const char* lable = "|/-\\";
while(count <= 101)
{
printf("[%-50s][%d%%]%c\r", bar, count - 1, lable[count%4]);
fflush(stdout); // 刷新
if(1 == count % 2)
{
bar[(count + 1) / 2 - 1] = '-';
}
else
{
bar[(count + 1) / 2 - 1] = '=';
}
++count;
usleep(100000); // 停顿间隔为 0.1 秒
}
printf("\n");
return 0;
}
运行完成结果: