8.3.1 文件、流和键盘输入
文件是一块存储信息的存储器区域。通常,文件被保存在某种类别的永久存储器上,例如软盘、硬盘或磁盘。
具有强大、灵活等特点的C语言具有许多打开、读取、写入和关闭文件的库函数。在一个级别上,它可以使用宿主操作系统的基本文件工具来处理文件。这被称为低级I/O。由于计算机系统之间存在许多差异,所以不可能创建一个通用的低级I/O函数标准库。然而,C还以第二种级别处理文件,称为标准I/O包。这包括创建用于处理文件的I/O函数的标准模型和标准集。
使用标准I/O包时,就屏蔽掉了这些差异。因此,要检查一个换行符,您可以使用if(ch=='\n')。如果该系统实际上使用回车/换行字符的组合,则I/O函数自动在两种表示法之间来回转换。
从概念上讲,C程序处理一个流而不是直接处理文件。流(stream)是一个理想化的数据流,实际输入或输出映射到这个数据流。这意味着具有不同属性的多种类型的输入由流表示,会具有更多统一的属性。于是打开文件的过程就成为将流与文件相关联,并通过流进行读写的过程。
第13单详细的讨论了文件。对本章来说,仅需注意C对待输入和输出设备与其对待存储设备上的普通文件相同。特别的是,键盘和显示设备作为每个C程序自动打开的文件来对待。键盘输入由一个被称为stdin的流表示,而到屏幕上的输出由一个被称为stdout的流表示。getchar() putchar() printf() scanf()函数都是标准I/O包的成员。这些函数同这两个流打交道。
所有这些的一个结论是可以使用与处理文件相同的技术来处理键盘输入。例如,读取文件的程序需要一种方法来检测文件的结尾,以 了解停止读取的位置。因此,C输入函数装备有一个内置的文件尾检测器。因为键盘输入是像文件一样被看待的,所以也应该能使用该文件尾检测器来终止键盘输入。
8.3.2 文件结尾
计算机操作系统需要某种方式来判定每个文件起始和结束的位置。检测文件结尾的一种方法是在文件中放置一个特殊字符来标志结尾。
第二种方法是让操作系统存储文件大小的信息。如果一个文件具有3000字节,而且程序已经读取了3000字节,则该程序就到达了文件尾。MS-DOS家庭对二进制文件使用这种方法,因为此方法允许文件拥有包括ctrl+z在内的所有字符。DOS的最新版本对文本文件也使用这种方法。Unix对所有文件都使用此方法。
对于这两种不同的方法,C的处理方式是让getchar()函数在到达文件结尾时返回一个特殊的值,而不去管操作系统是如何检测文件结尾的。赋予该值的名称是EOF(End of file)。因此,检测到文件尾时,getchar()的返回值是EOF。scanf()函数在检测到文件结尾时也返回EOF。通常EOF在stdio.h文件中定义:#define EOF (-1)。
为什么是-1?一般情况下getchar()返回一个范围在0-127之间的值,因为这些值是与标准字符集相对应的值。但如果系统识别一个扩展的字符集,则可能返回从0-255的值。在每种情况中,值-1都不对应任何字符,所以可以用它来表示文件结尾。
一些系统也许将EOF定义为-1以外的值,但该定义总是与合法的输入字符所产生的返回值不同。如果您包括了stdio.h文件并使用EOF符号,则您就不必考虑这个数值的定义。重要的是EOF代表的值表示检测到文件结尾,这个值并不是实际出现在文件中的一个符号。
如何在程序中使用EOF呢?将getchar()的返回值与EOF进行比较。如果不相同,则还没有到达文件结尾。换句话说,您可以使用如下表达式:
while ((ch=getchar())!=EOF)
如果您读取的是键盘输入而不是一个文件又会如何?大多数系统具有一种从键盘模拟文件结尾条件的方法。了解了这一点,您就可以重写基本的读取和回显程序,如程序清单8.2中所示:
/*echo_eof.c --重复输入,直到文件的结尾*/
#include <stdio.h>
int main (void)
{
int ch;
while((ch=getchar())!=EOF)
putchar(ch);
return 0;
}
注意以下几点:
1、不必定义EOF,stdio.h负责定义它;
2、不必担心EOF的实际值,因为stdio.h中的#define语句使您能够使用EOF进行符号表示。不应编写假定EOF具有某个特定值的代码;
3、变量ch从char类型改变为int类型。这是因为char变量可以由范围在0-255中的无符号整数来表示,但EOF可能具有数值-1.该值对无符号char变量是不可能的值,但对int则是可能的。幸运的是getchar()本身的类型实际上是int,所以它可以读取EOF字符。在使用有符号char类型的实现中,将ch声明为char类型仍然是可以的,但最好是使用更通用的形式。
4、ch是整数的事实不会对putchar()有任何影响。该函数仍打印与其相对应的字符 。
5、要对键盘使用此程序,您需要一种键入EOF字符的方式。不能简单的键入E\O\F,而且您也不能只键入-1.正确的方法是,您必须知道您的系统要求。例如,在大多数unix系统上,在一行的开始键入ctrl+D会导致传送文件尾信号。许多微型计算机系统将一行的开始位置键入ctrl+z识别为文件尾信号,还有一些则把任意位置的ctrl+Z解释成文件尾信号。
我们来考虑一下echo_eof.c可能发生的行为。它把您传给它的任何输入都复制到屏幕上。假设您能以某种方式将一个文件传送给该 程序。它会在屏幕上打印文件的内容,并在发现一个EOF信号即到达文件尾时停止。另一方面,假设您能找到一种方式将程序的输出定向到一个文件,您就可以从键盘输入数据,并使用echo_eof.c来将您键入的内容存储在一个文件中。假设您同时做这两件事:将来自一个文件的输入定向到echo_eof.c并将输出发送到另一个文件。这样你尺可以使用echo_eof来复制文件。这个小程序具有下列潜在的能力:查看文件内容,创建新文件,以及制作文件副本。关键是要控制输入和输出流,这就是下一节的话题。
来源:oschina
链接:https://my.oschina.net/u/2754880/blog/701172