缓冲区:
分为三种:空缓冲,行缓冲,全缓冲。
1.空缓冲: 没有缓冲,也就是信息在输入输出的时候,立马输入或输出。(eg:标准错误流stderr)
2.行缓冲: 当输入输出的时候,遇到换行才执行I/O操作。(eg:键盘的操作)
3.全缓冲: 当输入输出写满缓冲区才执行I/O操作。(eg:磁盘的读写)
几种情况及其现象:
1.
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("hehe ");
sleep(3);
return 0;
}
现象:停了3秒之后显示hehe,并没有换行
2.
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("hehe \n");
sleep(3);
return 0;
}
现象:停了3秒之后显示hehe,换行
3.
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("hehe \n");
fprintf(stderr,"haha \n");
sleep(3);
return 0;
}
现象:直接输出
hehe
haha
然后停三秒
4.
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("hehe \n");
sleep(3);
fprintf(stderr,"haha \n");
return 0;
}
现象:先输出
hehe
然后停三秒,再输出
haha
进度条:
实现进度条使用的是printf函数,printf输出函数是一个行缓冲函数,先写到缓冲区,满足条件就将缓冲区刷到对应文件中。满足下列条件之一,缓冲区都会刷新:
(1)缓冲区填满
(2)写入的字符中有’\n”\r’
(3)调用fflush刷新缓冲区
(4)调用scanf从缓冲区获取数据时,也会刷新新缓冲区。
因为实现进度条用的是行缓冲(printf),所以我们需要使用缓冲区刷新函数fflush来输出。否则我们看到的进度条将是一段一段输出的。
其中:
区分 ‘\r’和”\n’:
‘\r’: 表示回车,每次回到行首
‘\n’: 表示换行,将光标指向下一行的开头位置
所以我们应该用的是’\r’.
用Makefile实现进度条:
main.c
#include "progressbar.h"
int main()
{
char buf[102] = "#";
char *r = "-/|-\\";
ProgressBar(buf,r);
}
progressbar.c
#include "progressbar.h"
void ProgressBar(char buf[],char *r)
{
int i = 0;
while(i<=100)
{
printf("\033[33m[%-100s][%d%%][%c]\033[0m\r",buf,i,r[i%5]);
fflush(stdout);
buf[i++] = '#';
usleep(100000);
}
printf("\n");
}
progressbar.h
#ifndef __PRB_H__
#define __PRB_H__
#include <stdio.h>
#include <unistd.h>
#include <string.h>
void ProgressBar(char buf[],char *r);
#endif //__PRB_H__
Makefile:
.PHONY:main clean
main: main.o progressbar.o
gcc $^ -o $@
%.o : %.c
gcc -c $^ -o $@
clean:
rm -rf *.o