IO函数分类
输入函数分为缓冲输入和无缓冲输入,无缓冲输入在用户输入完之后立即打印字符,缓冲输入是在用户输入某个特定值之前系统是不会打印的。
缓冲区Buffer
- 无缓冲输入,程序立即使用输入内容。
- 缓冲输入,用户输入的字符被收集到一个称为缓冲区的临时存储区,按下enter程序才会使用用户输入的字符。
缓冲区给用户提供了在键盘上修改错误的机会,但是有时候在一些交互的程序中我们也会需要无缓冲输入。
缓冲的分类
缓冲分为完全缓冲IO和行缓冲IO,完全缓冲指缓冲区被填满才会刷新(读取),行缓冲指按下 enter 猜刷新缓冲区。在C语言中一般是行缓冲,文件读取会用到完全缓冲。
底层IO(low-level IO)和标准高级IO
操作系统提供的IO函数称为底层IO,各个操作系统的文件存储方式,回车符和换行符号的表示不一样等等,所以底层IO不会写在库里。C语言只支持标准高级IO。
CPU的指令集不同,也就是说汇编语言完全不一样。为其中一种架构写的程序,如果要移植到另一种架构上,基本上要全部重写。C语言跨平台是指C语言的编译器和它的标准库使得同一段C语言代码可以被编译成各种CPU指令集上的指令,并且执行结果相同。标准高级IO就是这样的一个高级标准库。
使用标准IO编译器会把if(x == '\n')
编译出符合系统的代码
文件结尾
为什么 IO 要涉及到文件呢?因为处理输入输出和处理文件的读写是一致的,文件结束通常会有两种机制,一种是在文件末尾放入一个特殊标志,二是记录文件大小。在C语言中无论系统怎么实现文件结尾,iO 函数例如getchar遇到文件结尾时还是会返回一个特殊的值 EOF,标志着读取到了文件结尾。
# define EOF -1
为什么是-1,因为通常getchar的返回值介于 0 到 127 的 ascll 码,不对应任何一个字符。绝大部分系统都能通过键盘来模拟文件结尾,ctrl + d/z 。
重定向
程序本身并不知道(或关心)输入是来自文件而不是来自键盘。C将文件和 I/O 设备置于相同的地位,所以现在这个文件就是 I/O 设备。
# include<stdio.h>
int main()
{
int ch;
while((ch=getchar())!=EOF){
putchar(ch);
}
return 0;
}
在UNIX,Linux/Windows 中,< 和 > 以及 >> 代表重定向,下面是使用示例:
//test是test.c编译出的可执行文件
./test>work
./test<work
- 重定向不能读取多个或者向多个文件输出
- 只能一个可执行文件和一个数据文件
./test < work1 > work2
重定向不在乎顺序运算符用累加的方法将数据输出到指定的文件上,不会覆盖已有的数据
getchar/putcahr
两个函数只操作一个单个的字符,getchar 会读取每一个字符包括空格,回车,制表,而 scanf 则会跳过这些字符。
puts
puts (字符数组) 其作用是将一个字符串(以’\0’结束的字符序列)输出到终端。将字符串结束标志 ‘\0’ 转换成 ‘\n’ , 即输出完字符串后换行。
字节流
我们使用键盘输入 is 42 时,在我们眼中有字符有数字,实际上在程序眼中是一个字节流,第一个字节是 i 的字符编码,第二个是 s 的字符编码, 第三个是空格的字符编码。虽然我们输入的都是字符但是我们可以转换成整数或者浮点数,例如scanf的%d连续读取两个字符 4 和 2 ,再转换成相应的整数。
简言之,输入由字符组成,使用 scanf 和 getchar 会接受所有的字符,而使用转换说明 %d 或者 %f 则限制流可接受输入的字符类型。