游戏开发工具

1.什么是缓冲区?

        缓冲区又被称为缓存,是内存空间的一部分,也就是说在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分存储空间就叫做缓冲区。

        缓冲区根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区。


2.为什么要引入缓冲区?

        比如我们要从磁盘中读数据,我们先把读出的数据放到缓冲区中,计算机再从缓冲区中取出数据,等缓冲区中的数据取完后,再从磁盘中读取数据,这样可以减少磁盘的读写次数,再加上计算机对缓冲区的操作大大快于对磁盘的操作,所以应用缓冲区可以大大提高读写速度。

        又比如使用打印机打印文档,由于打印机的打印速度相对较慢,我们先把文档输出到打印机相应的缓冲区,打印机再自行逐步打印 ,这时我们的cpu可以处理别的事情。

        缓冲区就是一块内存空间,以scanf()和printf()为例,它用在输入输出设备和cpu之间,用来缓存数据。它使得低俗的输入输出设备和高速的cpu能够协调工作,避免低俗的输入输出设备占用cpu。

输入设备->输入缓冲区->程序              程序->输出缓冲区->输出设备


3.缓冲区的类型

全缓冲:当填满标准I/O缓存后才进行实际的I/O操作,全缓冲的典型代表是对磁盘文件的读写。

行缓冲:当在输入和输出中遇到换行符时或满一行(1024个字节)才会刷新,即把数据从缓冲区中取出来。

不带缓冲:不进行缓冲,标准出错情况stderr是典型代表,这使得出错信息可以直接尽快地显示出来。


4.刷新的条件

标准输入输出是行缓冲,行缓冲刷新需要满足的条件有:

    满刷新,即一行满了(1024个字节)才刷新

    遇到 '\n'会刷新

    调用fflush()函数

    程序结束

下面我们说一下scanf()函数使用时的一些问题

#include <stdio.h>
int main()
{
   int a = 1, b = 2, c = 3, d = 4;  
   scanf("%d", &a);
   scanf("%d", &b);
   printf("a=%d, b=%d\n", a, b);
   scanf("%d %d", &c, &d);
   printf("c=%d, d=%d\n", c, d);

   return 0;
}

1.png

这里我们看到前两个数据被正确读取了,剩下一个a10,而第三个scanf()函数要求输入两个十进制整型,而a10无论如何也不符合要求,所以从结果中,我们看到读取失败了。

由此可见,scanf()在遇到不符合要求的数据时,会读取失败,不会跳过不符合要求的数据,继续等待用户输入。

下面我们把代码稍作修改

#include <stdio.h>
int main()
{
   int a = 1, b = 2, c = 3, d = 4;  
   scanf("%d", &a);
   scanf("%d", &b);
   printf("a=%d, b=%d\n", a, b);
   scanf("%d", &c);
   scanf("d=%d", &d);
   printf("c=%d, d=%d\n", c, d);

   return 0;
}

1.png

这里我们可以看出第三个scanf()函数遇到d=40时读取失败,而第四个scanf()函数把d=40读走了,这说明scancf()函数在遇到不符合输入格式的数据时,会读取失败,但不符合输入的数据依然保留在缓冲区中。

下面我们再来分析一段代码

#include <stdio.h>
int main()
{
   int a = 1, b = 2;
   scanf("a=%d", &a);
   scanf("b=%d", &b);
   printf("a=%d, b=%d\n", a, b);
   return 0;
}

1.png

这里我们只是输入了一个a=10,第一个scanf()函数正确读走了数据,但是第二个scanf()函数还没有开始读取数据,没有等待用户输入数据,程序就结束了。

这是因为我们在输入a=10后还敲了一次回车键,也就是给缓冲区键入了一个换行符 '\n' ,而字符 '\n'不符合b=%d这样的输入格式,造成第二个scanf()函数读取失败。


如果我们换种输入方式呢?

1.png

这次我们就读取正确了,这里注意a=10和b=20之间是没有空格的,那如果有空格呢,结果会如何呢?

2.png

这里我们看到第二个scanf()函数又读取失败了,这是因为在缓冲区中,a=10被读走后,接下来是一个空格字符,而空格字符显然不符合我的b=%d这样的输入格式,所以第二个scanf()函数读取失败。


总结一下:

        1. scanf()函数在以%d形式读取数据时,会跳过空格,换行,Tab这些空白字符,遇到形如a10这样不符合要求的数据时,会读取失败;

        2. scanf()函数在以a=%d形式读取数据时,不会跳过空格,换行,Tab这些空白字符,在遇到这些空白字符或其他不符合要求的数据时会读取失败。

        3. 如果数据不符合输入格式,则scanf()函数会读取失败,不再寻找输入缓冲区中后面的数据,不再等待用户输入新的数据,(即该scanf()函数调用结束),但不符合格式的数据依然保留在缓冲区中。

        4.scanf()函数在以%c形式读取数据时不会跳过字符

        5.scanf()函数在以%s形式读取数据时遇到空格终止读取,若要读取一行,可用gets()函数。