嵌入式学习——C语言基础
三、输入输出流、缓冲区
前言
C语言中我们用到的最频繁的输入输出方式就是scanf()与printf()。
scanf(): 从标准输入设备(键盘)读取数据,并将值存放在变量中。
printf(): 将指定的文字/字符串输出到标准输出设备(屏幕)。
注意宽度输出和精度输出控制, C语言借助了相应的缓冲区来进行输入与输出。
一、什么是流?
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称。
流的本质是数据传输,从外部输入设备向计算机内存输入,和从计算机内存向外部输输出设备传输的过程。
这其中按照数据的流向分为输入和输出流:
输入流:将数据读取到程序(内存)中。
输出流:将数据从内存输出到外部设备。
按照传输数据大小还可分为字符流和字节流。
二、浅谈输入输出缓冲区
1.那先聊聊为什么引入缓冲区:
计算机处理数据的速度是飞快的,而输入和输出设备跟cpu处理数据的速度不在一个量级,若没有缓冲区,就会出现cpu长时间等待的问题,白白浪费cpu性能。 引入缓冲区后,将输入的数据先放入缓冲区,待输入完成后再由cpu去读,既降低了读写次数,又提高了计算机运行速度。输出同样道理。
结合缓存区谈输入函数
从本质上讲,我们从键盘输入的数据并没有直接交给 scanf(),而是暂时保存到缓冲区中,直到我们按下回车键,scanf() 才从缓冲区中读取数据,赋值给变量。如果缓冲区中的数据符合 scanf() 的要求,那么就读取结束;如果不符合要求,那么就继续等待用户输入,或者干脆读取失败。scanf() 匹配到想要的数据后,会将匹配到的数据从缓冲区中删除,而没有匹配到的数据仍然会留在缓冲区中。输出亦然。如下图:
- 缓冲区分为三种类型:全缓冲、行缓冲和不带缓冲。
全缓冲:当填满缓冲区后才进行实际I/O操作。全缓冲的典型代表是对磁盘文件的读写。
行缓冲:当在输入和输出中遇到换行符时,执行真正的I/O操作。这时,我们输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O操作。典型代表是标准输入(stdin)和标准输出(stdout)。
不带缓冲:也就是不进行缓冲,标准错误文件 stderr 是典型代表,这使得出错信息可以直接尽快地显示出来。
- 缓冲区大小
如果没有自行设置缓冲区的话,系统会默认为标准输入输出设置一个缓冲区,这个缓冲区的大小通常是512个字节的大小。
缓冲区大小由 stdio.h 头文件中的宏 BUFSIZ 定义,如果希望查看它的大小,包含头文件,直接输出它的值即可: printf("%d", BUFSIZ);
- 缓冲区的刷新(清空)
下列情况会引发缓冲区的刷新:
- 缓冲区满时;
- 行缓冲区遇到回车时;
- 关闭文件;
使用特定函数刷新缓冲区。
多个 scanf() 之间要注意清空缓冲区。
清空缓冲区主要有两种思路:一是将缓冲区中的数据丢弃,二是将缓冲区中的数据读取出来,但是却不使用。
建议使用scanf("%*[^\n]%*c");
2.c预言的输入输出
- 输入函数
scanf()
可以读取多种类型数据。
scanf("格式控制字符",变量地址);
注意: 格式控制字符:用于控制输入数据格式,必须以引号引导,内容由一个或多个格式控制字符组成(%d、%c…),也可含有普通字符(“数据=%d”),普通字符必须在对应位置输入。但对空格字符要求较为宽松。
变量地址:用于存放数据的地址,scanf会把输入写入,有多个地址时,需用逗号隔开。
scanf()结合通配符,实现输入的筛选。
scanf("%[^\n]d",str);//可获取带空格字符串
scanf("%[a-zA-Z]c",str);//获取纯字母
2.输出函数
printf()
可以输出各种类型数据。
printf("格式控制字符串",参数);
注意:格式控制字符串:必须以引号引导,内容由一个或多个格式控制字符组合而成,也可以含普通字符,普通字符按原样在对应位置输出,也可以含转义字符。
参数:输出多个参数时,用逗号隔开哦。
printf()加上标志字符实现满足需求的输出
printf();
/*
- : 表示左对齐。如果没有,就按照默认的对齐方式,默认一般为右对齐
+ : 用于整数或者小数,表示输出符号(正负号)。如果没有,那么只有负数才会输出符号
空格 : 用于整数或者小数,输出值为正时冠以空格,为负时冠以负号
# : 用于八进制和十六进制整数时,表示在输出时添加前缀; 用于小数时,表示强迫输出小数点
*/
三、浅谈getchar()
先来看一下 getchar() ,其原型为: int getchar(void);
程序调用getchar()函数时,程序就等着用户按键,并等用户按下回车键返回。期间按下的字符存放在缓冲区,第一个字符作为函数返回值。继续调用getchar()函数,将不再等用户按键,而是返回您刚才输入的第2个字符;继续调用,返回第3个字符,直到缓冲区中的字符读完后,才等待用户按键。
getchar()函数的执行就是采用了行缓冲。第一次调用getchar()函数,会让程序使用者(用户)输入一行字符并直至按下回车键 函数才返回。此时用户输入的字符和回车符都存放在行缓冲区。再次调用getchar()函数,会逐步输出行缓冲区的内容。
看例子:
运行结果
稍稍改动:
运行结果:
当缓冲区中有数据时,不在等待用户输入。
总结
以上就是今天要讲的内容,输入输出流以及缓冲区浅薄的理解。