一:思考思路
1:简单进度条的模型类似于 [ ] [% 0]
[# ] [%10]
实际上就是将" # "填充到空白的地方(注:可以用没有任何数据元素的一组字符数组来表示),保持左右中括号不变(注:由输出语句中格式控制符来控制)
2:什么是回车和换行?
LIUNX环境下->回车与换行,实际上在狭义的解释就像我们写字,当一页纸我们从第一行第一列写到第一行最后一列,然后笔尖从第一行最后一列 转到 第二行最后一列,这个就叫做换行 (\n),而从第二行最后一列 转到 第二行第一列 叫做回车(\r)。
3:printf的缓冲区问题
在printf的实现中有一步调用write的操作。而write是一个系统调用,系统调用是软中断,频繁调用会使内核频繁陷入内核态,效率不是很高,所以printf的实现中在调用write之前,加了一个IO缓冲区。printf输出数据的时候实际上是先往用户空间的IO缓冲区写,在满足条件的情况下才会调用write并且刷新缓冲区,这样会提高内核工作的效率。
满足条件的情况有以下几种:
- 缓冲区填满;
- 写入的字符中有‘\n’;
- 调用fflush函数手动刷新缓冲区;
- 调用scanf要从缓冲区中读数据时,也会将缓冲区的数据刷新;
- printf语句生命结束时;
满足上面任意一个条件,缓冲区都会进行刷新,然后将数据输出至屏幕。缓冲区的大小一般为1024bytes,我们进度条的实现最多输出不到150个字符而且后面还不能加‘\n’换行符。所以我们只能在每次printf后面调用fflush手动刷新IO缓冲区,以达到在sleep之前输出printf内容的目的。
如上图所示,该输出结果的3秒后才输出 hehe
修改后 正常瞬间输出
4:思考
我们以一个字符数组 str [101] 作为被填充体, 以' # '作为填充物,数组的最后一个元素为 ' \0 ',一个' # '表示完成进度条的 1 %,每一个进度条得提升,我们就输出一次字符数组,再利用回车的特性,综合循环结构便可以完成这个代码
二:代码实现
#include<stdio.h>
#include <unistd.h>
int main()
{
int i = 0;
char str[101];
char arr[5] = "-\\|/";
str[0] = '\0';
while(i < 100)
{
str[i++] = '#';
str[i] = '\0';
printf("[%-100s][%%%d][%c]\r",str,i,arr[i%4]);
fflush(stdout);
usleep(50000);
}
printf("\n");
}