模拟进度条

来源:互联网 发布:linux 修改ip命令 编辑:程序博客网 时间:2024/06/05 14:56

本文通过编写模拟进度条程序来记录一些知识点,进度条始终在同一行显示,且不断的增加打印*个数以表示进度增加,程序如下:

  1 #include <stdio.h>  2   3 void display_progress(int num)  4 {  5     int i = 0;  6   7     for (i = 0; i < num; i++)  8     {  9         printf("*"); 10     } 11  12     return; 13 } 14  15  16 int main(void) 17 { 18     int i = 0; 19  20     for (i = 0; i <= 100; i++) 21     { 22         printf("\r"); 23         display_progress(i); 24         fflush(stdout); 25         sleep(1); 26     } 27  28     printf("\n"); 29  30     return 0; 31 }

1、回车和换行 \r\n
'\r'回车符的意思是将光标移动到当前行的开始
'\n'换行符的意思则是将光标移动到下一行

在windows系统中是通过 "\r\n"实现换行操作
在linux系统中是通过"\n"实现换行操作


2、缓冲与缓存
一直没搞明白,缓冲和缓存是否可以混着用,我自己理解是缓冲是一种操作,用于该种操作的地方叫缓存,即缓冲区等于缓存。

(1)全缓冲 缓冲区填满才进行实际的I/O操作
(2)行缓冲 遇到换行符时才进行实际的I/O操作,如缓冲区满了,即便没遇到换行符也进行I/O操作
(3)无缓冲


3、printf函数
printf是一个行缓冲函数,先写到缓冲区,满足条件后,才将缓冲区刷到对应文件中,刷新缓冲区的条件如下:
1 缓冲区填满 (printf行缓冲区大小为1024字节)
2 遇到'\n' 或 '\r' 字符
3 调用fflush手动刷新缓冲区
4 调用scanf从缓冲区中读取数据

满足上面4个条件之一缓冲区就会刷新, 将数据写入到对应的文件
当我们执行printf的进程或者线程结束的时候会主动调用fflush来刷新缓冲区,所以程序结束,也会刷新

有时候会遇到该有的打印没有显示,就注意下是不是printf没有添加'\n'符号。
对与本程序而言,进度条需一直在同一行显示,固不能有'\n'进行换行操作,数据需通过fflush手动刷新到标准输出。



4、文件的写同步sync
让我想起另一个问题,记得有次往sd卡写数据,显示write接口已返回成功,我便拔掉了SD卡,结果查看数据并没有写完全。
这里存在的问题是在UNIX系统中,write函数是把数据从进程缓冲区拷贝到内核缓冲区当中便返回了,当缓冲区满或者内核要重用该缓冲区时,才把该缓冲区的数据排入输出队列,然后等到其到达队首时,才进行实际的I/O操作。即实际的写磁盘操作则可能在以后的某个时刻进行。这被称为延迟写,这样做的目的是减少系统调用,提高CPU的工作效率。如要及时同步磁盘文件,则可通过sync、fsync和fdatasync三个函数实现。

void sync(void);
sync函数只是将内核缓冲区的数据排入到输出队列就返回了,并没有进行实际的I/O操作。系统守护进程一般每隔一段时间就会调用该函数。

int fsync(int fd);
fsync与sync不同之处在于它等待写磁盘操作结束才返回,保证数据已同步到磁盘文件。

int fdatasync(int fd);
类似与fsync,不同之处在于只保存文件数据同步,不包括文件本身的特征数据。


5、fflush与fsync的关系
如通过fwrite库函数将数据写到文件当中,数据只是先写到了流缓冲区当中,可通过fflush只刷新位于流缓冲区中的数据,将其写到内核缓冲区当中,并不保证及时写到磁盘文件当中。固要及时同步还需调用fsync库函数实现。


存在问题
上述程序在运行过程中,如缩小屏幕宽度,那么在运行一段时间后,当屏幕宽度装不下一行打印的时候,自动分成了两行打印,而下一次的 “\r”操作只是回到了分2行后的第二行开头,这时变出现非预期的打印了,这种情况我还不知道怎么处理,如有清楚的,麻烦跟我讲解下,谢谢。


参考资料
http://www.ruanyifeng.com/blog/2006/04/post_213.html (讲述回车换行的来历,建议看下评论)
http://www.2cto.com/os/201409/339460.html  (同步内核缓冲区讲解)
《UNIX环境高级编程》

0 0