Linux进度条小程序(结合缓冲区相关知识)

一.行缓冲

#include<stdio.h>
#include<string.h>
#include<unistd.h>
int main()
{
    
    
        printf("hello world!\n");
        sleep(5);
}
#include<stdio.h>
#include<string.h>
#include<unistd.h>
int main()
{
    
    
        printf("hello world!");
        sleep(5);
}

在写我们的进度条之前,先讲一些补充知识,首先我们来看下面这两段代码,可以发现两段代码唯一的区别就是printf末尾加没加 \n ,可能很多同学认为这两段代码运行结果是一样的,但实际上运行之后我们可以看到第一段代码先打印出 hello world 再 sleep 5秒,第二段代码先 sleep 5 秒,再打印出 hello world

这是怎么回事呢? 莫非第二段代码 printf 和 sleep 的执行顺序变了? 当然不是,我们的代码肯定是从上到下依次执行的,printf 一定是先于 sleep 执行的, 真正的原因是 hello world 被缓存起来,并没有立即被刷新到显示器,当 sleep 5秒后,缓冲区的内容才被刷新出来,下面介绍一下缓冲区的分类

缓冲区的分类

全缓冲:我们缓存在缓冲区的东西在缓冲区满的时候,才写入磁盘或者我们调用fflush刷新缓冲区才能写入到磁盘。对于全缓冲,如果我们缓冲区没满,或者我们没有手动刷新缓存,那么缓存区的内容是不能写入到磁盘的。(对文件写入时采用全缓冲)

行缓冲:我们标准输入、标准输出都是采用的行缓存,也就是遇到换行符的时候,才会将缓存区的东西写入到磁盘。

无缓存:有的时候,我们希望一些内容在第一时间写入磁盘或者显示出来,比如我们显示错误信息的时候,这时候典型的例子比如标准出错,它就是直接显示出错信息,而不会先放入缓存。

通常情况下,我们需要知道的是,在缓冲区满、手动调用fflush、或者程序结束的时候,我们的缓冲区才会得到刷新,并写入磁盘。

由此,我们就可以知道原因了,hello world 按照行缓冲的方式缓存到缓冲区,遇到换行符才会被刷新到显示器上,所以第一段代码缓冲区里是 hello world\n,遇到换行符被刷新出来,第二段代码缓冲区里是 hello world,没有遇到换行符,直到程序结束,缓冲区的内容才被刷新出来

(1). 这个缓冲区在哪里 ?
(2). 这个缓冲区是谁提供的?
(3). OS也是有缓冲的 vs 文件缓冲

#include<stdio.h>
#include<unistd.h>
int main()
{
    
    
        printf("hello printf\n");
        fprintf(stdout,"hello fprintf\n");

        const char* buf = "hello write\n";
        write(1,buf,strlen(buf));

        fork();
        return 0;
}                    

这段代码我们 ./myproc 运行起来,结果如我们所想,但如果重定向到一个文件当中,结果就不如我们所想了
在这里插入图片描述

二.\n和\r

换到下一行 : 换行(\n)
回到一行的开始 : 回车(\r)

在C/C++中,\n 表示的有两个意思 : 回车 + 换行

在这里插入图片描述

我们平常键盘上的Enter键就是回车 + 换行的功能,这也是为什么Enter键上的图标是一弯箭头,表示换到下一行并回到下一行的开始

结合以上的知识,我们可以先写出一个简易的倒计时程序

#include<stdio.h>
#include<string.h>
#include<unistd.h>
int main()
{
    
    
        int i = 10;
        while(i)
        {
    
    
                printf("%2d\r",i);
                // 刷新缓冲区
                fflush(stdout);
                sleep(1);
                i--;
        }
}

三.进度条实现

#include<stdio.h>
#include<string.h>
#include<unistd.h>
int main()
{
    
    
        int i = 0;
        char proc[102];
        memset(proc,'\0',sizeof proc);
        const char* lable = "|/-\\";
        while(i <= 100)
        {
    
    
                printf("[%-100s][%d%%][%c]\r",proc,i,lable[i % 4]);
                // 刷新缓冲区
                fflush(stdout);
                proc[i] = '#';
                usleep(100000);
                i++;
        }
        printf("\n");
}

Guess you like

Origin blog.csdn.net/DR5200/article/details/119392312