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