分类: 系统运维
2012-03-28 17:35:13
一旦我们打开一个流,我们可以从以下三种无格式的I/O中选择:
1、一次一字符(Character-at-a-time)I/O。我们可以一次读写一个字符,而让标准I/O函数处理所有的缓冲事宜,如果流有缓冲的话。
2、一次一行(Line-at-a-time)I/O。如果我们读一次读写一行,我们使用fgets和fputs。每行都以一个换行符终止,而且当我们调用fgets时必须指定我们能处理的最大行长度。我们在5.7节讲述这两个函数。
3、直接(Direct)I/O。这种类型的I/O通过fread和fwrite函数支持。对于每个I/O操作,我们读写一些对象,而每个对象都有一个指定的尺寸。这两个函数经常用来处理二进制文件,那里我们每次操作读写一个结构。我们在5.9节讲述这两个函数。
术语“直接I/O”,从ISO C标准而来,有很多名字:二进制(binary)I/O、一次一对象(object-at-a-time)I/O、面向记录(record-oriented)I/O,或面向结构(structure-oriented)I/O。
(我们在5.11节讲述格式化I/O函数,比如printf和scanf。)
输入函数:
有三个允许我们一次读一个字符的函数。
函数getchar被定义为与getc(stdin)等价。前两个函数的区别是getc可以被作为一个宏而实现,而fgetc不能作为宏实现。这表明了三件事:
1、getc的参数不应该是有副作用的表达式。
2、因为fgetc被保证为一个函数,所以我们可以拿到它的地址。这允许我们把fgetc的地址作为另一个函数的参数。
3、fgetc的调用很可能比getc的调用时间长,因为调用一个函数的时间通常要更长。
这三个函数返回下一个字符,作为一个unsigned
char并转换为一个int。指定无符号的原因是为了高位位如果设置的话,不会返回一个负值。返回一个int值的原因是为了可以返回所有可能的字符值,以
及一个错误或碰到文件尾的标识。在
注意这些函数当碰到一个错误或到达文件尾时返回同一个值。为了区别这两者,我们必须调用ferror或feof。
在多数实现上,在FILE对象里为每个流维护了两个标志:
1、一个错误标志;
2、一个文件结束标志。
两个标志都可以调用clearerr来清除。
在从一个流读入后,我们可以调用ungetc来把字符放回去。
放回的字符会被后续在流上的读操作以放回的相反顺序返回。尽管如此,注意,虽然ISO C允许一个实现支持任意数量的放回,但一个实现只被要求提供单一字符的放回。我们不应该指望会多于一个字符。
我们放回的字符不必和我们之前读取的字符一样。我们可以放回EOF。但是当我们到达文件尾时,我们可以放回一个字符。下次读时会返回这个字符,再下次读会返回EOF。这得以工作是因为成功的ungetc操作会清除流的文件结束标识。
放回通常用在我们读一个输入流并把输入分为多个单词或一些格式的语素。有时我们需要预先查看下下一个字符来决定如何处理当前字符。我们可以很容易把预查的
字符放回,以便下次的getc返回它。如果标准I/O库没有提供这种放回的能力,那么我们必须把这个字符存储到我们自己的变量里,以及一个告诉我们下次需
要一个字符时使用这个字符而不是调用getc来获取字符的标志。
当我们用ungetc放回字符时,它们不会写入下层的文件或设备。它们被保存在标准I/O库的缓冲里。
输出函数
我们将找到对应于每个我们之前讨论过的输入函数的输出输出。
和输入函数相似,putchar(c)和putc(c, stdout)等价,而putc可以作为一个宏实现,但fputc不能作为一个宏实现。