一旦打开了流,则可在三种不同类型的非格式化I/O中进行选择,对其进行读、写操作:

(1)每次一个字符的I/O。一次读或写一个字符,如果流是带缓冲的,则标准I/O会处理所有缓冲。

(2)每次一行的I/O。如果想要一次读或写一行,则使用fgets和fputs。每行都以一个换行符终止。当调用fgets时,应说明能处理的最大行长。

(3)直接I/O。fread和fwrite函数支持这种类型的I/O。每次I/O操作读或写某种数量的对象,而每个对象具有指定的长度。这两个函数常用于从二进制文件中每次读或写一个结构。

直接I/O(direct I/O)这个术语来自ISO C标准,有时也被称为二进制I/O、一次一个对象I/O、面向记录的I/O或面向结构的I/O。

1、输入函数

以下三个函数可用于一次读一个字符。

  1. #include <stdio.h>
  2. int getc( FILE *fp );
  3. int fgetc( FILE *fp );
  4. int getchar( void );
  5. 三个函数的返回值:若成功则返回下一个字符,若已到达文件结尾或出错则返回EOF

函数getchar等价于getc(stdin)。前两个函数的区别是getc可被实现为宏,而fgetc则不能实现为宏。这意味着:

(1)getc的参数不应当是具有副作用的表达式。

(2)因为fgetc一定是一个函数,所以可以得到其地址。这就允许将fgetc的地址作为一个参数传送给另一个函数。

(3)调用fgetc所需时间很可能长于调用getc,因为调用函数通常所需的时间长于调用宏。

这三个函数在返回下一个字符时,会将其unsigned char类型转换为int类型。说明为不带符号的理由是,如果最高位为1也不会使返回值为负。要求整型返回值的理由是,这样就可以返回所有可能的字符再加上一个已出错或已到达文件尾端的指示值。在<stdio.h>中的常量EOF被要求是一个负值,其值经常是-1。这就意味着不能将这三个函数的返回值存放在一个字符变量中,以后还要将这些函数的返回值与常量EOF相比较。

注意,不管是出错还是到达文件尾端,这三个函数都返回同样的值。为了区分这两种不同的情况,必须调用ferror或feof。

  1. #include <stdio.h>
  2. int ferror( FILE *fp );
  3. int feof( FILE *fp );
  4. 两个函数返回值:若条件为真则返回非0值(真),否则返回0(假)
  5.  
  6. void clearerr( FILE *fp );

在大多数实现中,为每个流在FILE对象中维持了两个标志:

  • 出错标志。
  • 文件结束标志。

调用clearerr则清除这两个标志。

从流中读取数据以后,可以调用ungetc将字符再压送回流中。

  1. #include <stdio.h>
  2. int ungetc( int c, FILE *fp );
  3. 返回值:若成功则返回c,若出错则返回EOF

压送回流中的字符以后又可从流中读出,但读出的字符的顺序与压送回的顺序相反。应当了解,虽然ISO C允许实现支持任意次数的回送,但是它要求实现提供一次只送回一个字符。我们不能期望一次能送回多个字符。

回送的字符不必一定是上一次读到的字符。不能回送EOF,但是当已经达到文件尾端时,仍可以回送一个字符,下次读将返回该字符,再次读则返回EOF。之所以能这样做的原因是一次成功的ungetc调用会清除该流的文件结束标志。???(这原因解释的,越解释越糊涂)

当正在读一个输入流,并进行某种形式的分字或分记号操作时,会经常用到回送字符操作。有时需要先看一看下一个字符,以决定如何处理当前字符。然后就需要方便地将刚查看的字符送回,以便下一次调用getc时返回该字符。如果标准I/O库不提供回送能力,就需要将该字符存放到一个我们自己的变量中,并设置一个标志以便判别在下一次需要一个字符时是调用getc,还是从我们自己的变量中取用。

用ungetc压送回字符时,并没有将它们写到文件中或设备上,只是将它们写回标准I/O库的流缓冲区中。

2、输出函数

对应于上面所述的每个输入函数都有一个输出函数。

  1. #include <stdio.h>
  2. int putc( int c, FILE *fp );
  3. int fputc( int c, FILE *fp );
  4. int putchar( int c );
  5. 三个函数返回值:若成功则返回c,若出错则返回EOF

与输入函数一样,putchar(c)等效于putc(c,staout),putc可实现为宏,而fputc则不能实现为宏。

本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/

标准I/O库之读和写流的更多相关文章

  1. 标准I/O库之打开和关闭流

    下列三个函数打开一个标准I/O流. #include <stdio.h> FILE *fopen( const char *restrict pathname, const char *r ...

  2. UNIX环境高级编程——标准I/O库

    对一个进程预定义了三个流,并且这三个流可以自动的被进程使用,它们是:标准输入.标准输出.和标准错误. 标准I/O库提供缓冲的目的是尽可能减少使用read和write的次数. 标准I/O库提供了三种类型 ...

  3. UNIX环境高级编程 第5章 标准I/O库

    本章是关于C语言标准I/O库的,之所以在UNIX类系统的编程中会介绍C语言标准库,主要是因为UNIX和C之间具有密不可分的关系.由于UNIX系统存在很多实现,而每个实现都有自己的标准I/O库,为了统一 ...

  4. APUE(5)---标准I/O库 (2)

    六.读和写流 一旦打开了流,则可在3种不同类型的非格式化I/O中进行选择,对其进行读.写操作:1)每次一个字符的I/O,一次读或写一个字符,如果刘时代缓冲的,则标准I/O函数处理所有缓冲:2)每次一行 ...

  5. 第五章:标准I/O库

    本章用于解析C语言标准I/O库,之所以在UNIX类系统的编程中会介绍C语言标准库,主要是因为UNIX和C之间具有密不可分的关系. 标准I/O库相比于操作系统的I/O库,具有更高的效率和可移植性,前者是 ...

  6. 《UNIX环境高级编程》(APUE) 笔记第五章 - 标准I/O库

    5 - 标准I/O库 Github 地址 1. 标准 I/O 库作用 缓冲区分配 以优化的块长度执行 I/O 等 使用户不必担心如何选择使用正确的块长度 标准 I/O 最终都要调用第三章中的 I/O ...

  7. Linux C 文件操作,系统调用 -- open()、read() 和 标准I/O库 -- fopen()、fread()

    函数汇总: open().write().read().close() fopen().fwrite().fread().fclose() 一.什么是文件 在讲述文件操作之前,我们首先要知道什么是文件 ...

  8. boost.ASIO-可能是下一代C++标准的网络库

    曾几何时,Boost中有一个Socket库,但后来没有了下文,C++社区一直在翘首盼望一个标准网络库的出现,网络上开源的网络库也有不少,例如Apache Portable Runtime就是比较著名的 ...

  9. 标准I/O库之缓冲

    标准I/O库提供缓冲的目的是尽可能减少使用read和write调用的次数.它也对每个I/O流自动地进行缓冲管理,从而避免了应用程序需要考虑这一点所带来的麻烦. 标准I/O提供了三种类型的缓冲: (1) ...

随机推荐

  1. SQLite入门与分析(九)---VACUUM命令分析

    VACUUM命令是SQLite的一个扩展功能,模仿PostgreSQL中的相同命令而来.若调用VACUUM带一个表名或索引名, 则将整理该表或索引.在SQLite 1.0中,VACUUM命令调用 gd ...

  2. c while 循环

    c代码: #include <stdio.h> int main(void){ unsigned long sum=1UL; unsigned int j=1U; unsigned ; p ...

  3. function(a)

    问题:  问个初级的问题int a = 8;function(a);这里在function中的a值是引用a内存中的数据,还是新开辟内存后将a的值赋值到新内存供函数调用.  回答: int a = 8; ...

  4. ERP 实施和应用不成功共同点

    ERP 实施和应用不成功共同点     ERP 重新得到人们理性的关注并不意味着实施和应用ERP变得轻而易举了.如何才能实施好ERP?这仍然是关键的问题. 大部份企业应用ERP不成功的原因是什么,许多 ...

  5. Android开发UI之个性化控件之Menu

    MenuDrawer 滑出式菜单,通过拖动屏幕边缘滑出菜单,支持屏幕上下左右划出,支持当前View处于上下层,支持Windows边缘.ListView边缘.ViewPager变化划出菜单等. 项目地址 ...

  6. Java Memory Management(1)

    Java Memory Management, with its built-in garbage collection, is one of the language’s finest achiev ...

  7. hadoop2.2原理: 序列化浅析

    序列化是指将一个对象编码成字节流,之后从字节流中重构对象: 为什么需要序列化? 答:用序列化接口可以将对象实例从存储到本地文件或者传送到网络的另一端的节点上: 序列化过程: 序列化的三种主要用途: 1 ...

  8. [swustoj 585] 倒金字塔

    倒金字塔(0585) Time limit(ms): 3000 Memory limit(kb): 65535 Submission: 208 Accepted: 48   Description S ...

  9. Android学习之路——简易版微信为例(二)

    1 概述 从这篇博文开始,正式进入简易版微信的开发.深入学习前,想谈谈个人对Android程序开发一些理解,不一定正确,只是自己的一点想法.Android程序开发不像我们在大学时候写C控制台程序那样, ...

  10. .net,sessionState的Session共享问题解决方案

    最近项目因为要负载均衡所以就使用了sessionState的Session共享,但是却发现多台服务器中有个别服务器的Session没有共享,于是就有了这篇文章,下面开始说说. 这个基本上就分两种情况: ...