第 11 章 输入输出流类

42
11 11 第第第第第第 第第第第第第

Upload: tara-tillman

Post on 04-Jan-2016

119 views

Category:

Documents


2 download

DESCRIPTION

第 11 章 输入输出流类. 外部设备可分为 人机交互设备 和 存储设备 两个大类。 人机交互设备主要指键盘、显示器等终端控制台设备和打印机。 存储设备指磁带、磁(软、硬)盘、光盘等以文件形式存储持久数据的设备。. 早期程序设计语言中通常以文件方式来统一人机交互设备和存储设备的输入输出操作。即将人机交互设备当作一种特殊文件对待。 以文件方式统一管理外部设备可以屏蔽实际物理设备的差异,有利于整体上简化程序设计语言与外部设备交换信息的处理过程。. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第 11 章   输入输出流类

第第 1111 章 章 输入输出流输入输出流类类

Page 2: 第 11 章   输入输出流类

外部设备可分为人机交互设备和存储设备两个大类。

人机交互设备主要指键盘、显示器等终端控制台设备和打印机。

存储设备指磁带、磁(软、硬)盘、光盘等以文件形式存储持久数据的设备。

外部设备可分为人机交互设备和存储设备两个大类。

人机交互设备主要指键盘、显示器等终端控制台设备和打印机。

存储设备指磁带、磁(软、硬)盘、光盘等以文件形式存储持久数据的设备。

Page 3: 第 11 章   输入输出流类

早期程序设计语言中通常以文件方式来统一人机交互设备和存储设备的输入输出操作。即将人机交互设备当作一种特殊文件对待。

以文件方式统一管理外部设备可以屏蔽实际物理设备的差异,有利于整体上简化程序设计语言与外部设备交换信息的处理过程。

早期程序设计语言中通常以文件方式来统一人机交互设备和存储设备的输入输出操作。即将人机交互设备当作一种特殊文件对待。

以文件方式统一管理外部设备可以屏蔽实际物理设备的差异,有利于整体上简化程序设计语言与外部设备交换信息的处理过程。

Page 4: 第 11 章   输入输出流类

C++ 语言对输入输出的处理引入了“流”这个比文件抽象程度更高的概念。输入输出操作被看作数据在源设备对象与目标设备对象之间的流动。

C++ 中完成输入输出操作的类称为流类,并提供了可重用的流类库。

Page 5: 第 11 章   输入输出流类

11. 1 C++ 流库结构

标准 ANSI C 程序中的绝大部分工作是由 ANSI C 标准库中的 printf , scanf完成的, I/O 功能作为 ANSI C 标准库功能的一部分被提供。在 C++ 中 iostream库提供了 printf 、 scanf 功能的替代方法,输入输出功能的实现由一个 iostream 对象完成。

Page 6: 第 11 章   输入输出流类

1 . 流缓冲区类在 C++I/O 类库定义文件 iostream.h 中有一个 streambuf 类,它用来提供物理设备的接口。缓冲区由一段预留的字符存储空间和两个指针组成,两个指针分别指向字符要被插入或被取出的位置。 streambuf 类定义了一组缓冲或处理流的通用方法,诸如设置缓冲区,移动指针,存、取字符等。

conbuf strstreambuf

filebuf

streambuf

图 11.1 流缓冲区类的派生关系

C++ I/O 流类的结构(1 )

Page 7: 第 11 章   输入输出流类

streambuf 类有三个派生类,其中:

( 1 )       conbuf 在 constream.h 中定义,提供光标控制、清屏,定义活动窗口等控制台操作接口和 I/O 缓冲区管理功能。

( 2 )       filebuf 在 fstream.h 中定义,它用来维护文件缓冲区的打开,关闭,读、写,建立磁盘文件的内存代理。

( 3 )       strstreambuf 在 strstream.h 中定义,提供在内存进行提取和插入操作的缓冲区管理。

Page 8: 第 11 章   输入输出流类

2 .  输入输出流类iostream.h 中还有以 ios 类为基类的一组

流类的定义。 ios 类及其派生类均含有一个指向 stream

buf 类的指针。通过 streambuf 类代理物理设备的操作。

从类 ios 开始,逐级派生,形成了较为复杂的结构,要很好地使用 C++ 流类,必须逐级了解其父类的 public 、和 protected 类型的成员函数、成员变量。

Page 9: 第 11 章   输入输出流类

istream_withassign

ostream_withassign

strstreambase

ifstream

istrstream ofstream ostrstream

fstream strstream

iostream

iostream_ withassign

istream ostreamfstreambase

ios

图 11.2 ios 类的派生关系

C++ I/O 流类的结构(2 )

Page 10: 第 11 章   输入输出流类

流类分类 流类名称 流类作用

流基础类 ios 所有流类的父类、保存流的状态并处理错误

输入流类 istream 输入流基础类、将流缓冲区中的字符作格式化和非格式化之间的转换,并输入。

ifstream 文件输入流类

istream_withassign 为 cin 输入流类即操作符 >> 输入流

istrstream 串输入流类

输出流类 ostream 输出流的基础类、将流缓冲区中的数据格式化或非格式化转换,并输出。

ofstream 文件输出流类

ostream_withassign cout , cerr , clog 输出的流类即操作符 << 输出流。

ostrstream 串输出流类

文件流类 fstreambase 文件流基础类

串流 strstreambase 串流基础类

输入 / 输出流类

iostream 多目的输入 / 输出流类的基础类

fstream 文件流输入 / 输出类

strstream 串流输入 / 输出类

流类库成员列表

Page 11: 第 11 章   输入输出流类

上表中:( 1) 基础类 ios 是所有流类的根。它有四个直接派生类: is

tream 、 ostream 、 fstreambase 和 strstreambase ,它们是流类库中的基本流类。

( 2) istream 和 ostream 是 ios直接派生类 , 其功能是将数据格式化或非格式化数据与流缓冲区之间作转换处理。

( 3) istream_withassign , ostream_withassign 分别从 istream 和 ostream 类派生,并定义了 cin,cout 流,作标准输入和输出处理。

( 4 ) 而 iostream 是 istream 和 ostream 类的多继承派生类,用来操作文件流的标准输入 / 输出。

( 5 ) ifstream 是 istream 和 fstreambase 的多继承派生类,用于处理文件的输入。

( 6 ) ofstream 是 ostream 和 fstreambase 的多继承派生类,用于处理文件的输出。

Page 12: 第 11 章   输入输出流类

11. 2 C++ 输入与输出输入输出流可以从文件或设备中读出或写入数

据, C++运行库提供了两种输入输出功能。

( 1 )类输入 / 输出,把数据作为单字符流处理。可以处理简单的数据,也可以处理复杂的数据结构。

( 2 )直接调用操作系统的底层功能实现输入 / 输出操作。

每一类都有文件和标准的输入和输出功能。这里着重讨论使用流类的标准输入和输出,以及流类的文件输入和输出。

Page 13: 第 11 章   输入输出流类

11.2.1 标准输入输出标准输入与输出是指读键盘的数据和将数据

输出到屏幕。 C++ 用 istream_withassign 类和 ostream_withsaaign 类来实现标准输入输出功能。

iostream.h 文件中以下两句定义 cin 和 cout 两个标准流对象 :

istream_withassign cin;

ostream_withassign cout;

在标准输入类 istream_withassign 和标准输出类 ostream_withassign 分别对操作符“ >>” “<<” 进行了重载,用于完成对各种简单数据类型的输入和输出。

Page 14: 第 11 章   输入输出流类

11.2.2 格式化的输入输出

C++ 提供了两种格式控制函数用来控制输入输出的格式:

•ios 类中定义的格式控制成员函数•基于流对象的操纵函数。

相比之下操纵函数使用更为方便。下面重点介绍操纵函数的概念和用法。

Page 15: 第 11 章   输入输出流类

1 . ios 类中定义的格式控制标志ios 类中定义了一个数据成员:格式控制标志字 long x_flags

。 x_flags每一位的状态值用枚举符号常量定义。enum{ skipws =0x0001, //跳过输入空格 left =0x0002, // 输出左对齐调整 right =0x0004, // 输出右对齐调整 internal =0x0008, // 输出符号和基指示符后的填补 dec =0x0010, // 转换为十进制 (in/out) oct =0x0020, // 转换为八进制 (in/out) hex =0x0040, // 转换为十六进制 (in/out) showbase=0x0080, // 输出显示基指示符 showpoint=0x0100, // 输出显示小数点 uppercase=0x0200, // 大写十六进制输出 showpos =0x0400, //正整数显示前加上” +” scientific=0x0800, // 输出用科学表示法表示浮点数 fixed =0x1000, // 输出用固定小数点表示浮点数 unitbuf =0x2000, // 在输出操作后刷新所有流 stdio =0x4000 // 在输出后刷新 stdout 和 stderr};

Page 16: 第 11 章   输入输出流类

long x_flags = 0x0080 = 0000 0000 1000 0000输出显示基指示符

long x_flags = 0x0003 = 0000 0000 0000 0011跳过输入空格

& 输出左对齐调整

long x_flags = 0x0083 = 0000 0000 1000 0011跳过输入空格

& 输出左对齐调整 & 输出显示基指示符

long x_flags 标志可以由 ios 类的成员函数 flags(), setf() 和 unsetf()访问,也可以用操纵函数操作。

Page 17: 第 11 章   输入输出流类

2 .操纵函数和操纵符

操纵函数分为带参数和不带参数两种。不带参数的操纵函数又叫操纵符。操纵符定义在头文件 iostream.h 中,操纵函数定义在头文件 iomanip.h 中 .

 

Page 18: 第 11 章   输入输出流类

表 11.2 iostream.h 中的操纵符

操作符 用法举例 结果说明

dec 

cout<<dec<<intvar;cin>>dec>>intvar;

将整数转化为十进制格式输出将整数转化为十进制格式输入

hex cout<<hex<<intvar;cin>>hex>>intvar;

将整数转化为十六进制格式输出将整数转化为十六进制格式输入

oct cout<<oct<<intvar;cin>>oct>>intvar;

将整数转化为八进制格式输出将整数转化为八进制格式输入

ws cin>>ws; 忽略输入流中的空格

endl cout>>endl; 插入换行符 ,刷新流

ends cout>>ends; 插入串最后的串结束符

flush cout>>flush; 刷新一个输入流

Page 19: 第 11 章   输入输出流类

表 11.3 iomanip.h 中的操纵函数 setprecision(in

t)cout<<setprecision(6)cin>>setprecision(15)

输出浮点数精度为 6 位小数输入浮点数精度为 15 位小数

setw(int) cout<<setw(6)<<var;cin>>setw(24)>>buf;

输出数据宽度为 6输入数据宽度为 24

setiosflags(long)

cout<<setioflags(ios::hex| ios::uppercase)cin>>setioflags(ios::oct| ios::skipws)

指定数据输出的格式为十六进制格式且用大写字母输出指定数据输入的格式为八进制格式且跳过输入中的空白

resetiosflags(long)

cout<< resetiosflags(ios::dec)cin>>resetiosflags(ios::hex)

取消数据输出的格式为十进制格式取消数据输入的格式为十进制格式

Page 20: 第 11 章   输入输出流类

例 11. 1 操纵符的使用#include <iostream.h>#include <iomanip.h>void main(){ double values[] = { 1.23, 35.36, 653.7, 4358.24 }; char *names[] = { "Zoot", "Jimmy", "Al", "Stan" }; cout << setiosflags( ios::fixed );//浮点数使用普通记数法表示 for ( int i = 0; i < 4; i++ ) cout << setiosflags( ios::left) // 设置左对齐 << setw(6) // 设置数据宽度为 6 位 << names[i] << resetiosflags( ios::left ) //撤消左对齐 << setw( 10 ) // 设置数据宽度为 10 位 << setprecision(1) // 设置浮点数精度 1 位 << values[i] << endl;}

输出为:Zoot 1.2Jimmy 35.4Al 653.7Stan 4358.2

Page 21: 第 11 章   输入输出流类

11. 3 流类运算符重载

使用传统的 C 语言中 printf,scanf 等输入输出函数编写的程序,当输入输出的数据类型发生变化时,必须重写所有的输入输出代码。使用 C++ 流类后,这个问题不复存在。

C++ 利用流类对象 cin 、 cout 的成员函数重载任意类的输入输出操作。

流的输入运算符” >>”又称提取运算符,流的输出运算符” <<”又称插入运算符,它们都可以重载。

Page 22: 第 11 章   输入输出流类

例:用户定义的日期 Date 类的输入输出。

为保持和简单类型的输入输出同样的形式,需要为 Date 类重载操作符 << 和 >>。

由于重载的函数需要访问 Date 类的私有的和受保护的成员,应该把这些重载的函数定义为 Date 类的友元。

Page 23: 第 11 章   输入输出流类

#include <iostream.h>class Date{int mo, da, yr;public: Date( int m, int d, int y ) { mo = m; da = d; yr = y; } friend ostream& operator<< ( ostream& os, Date& dt ); friend istream& operator>> ( istream& is, Date& dt ); };ostream& operator<<( ostream& os, Date& dt ){ os << dt.mo << '/' << dt.da << '/' << dt.yr; return os; //返回流的引用}istream & operator>>(istream& is, Date& dt ){ is >> dt.mo >> dt.da>>dt.yr; return is; //返回流的引用}

void main(){ int mo, da, yr; Date dt( 7,1, 1997 ); cout<<dt<<endl; cin>>mo>>da>>yr; Date otherdt( mo, da, yr ); cout << otherdt<<endl; Date dt_input( 0, 0, 0 ); cin>> dt_input; cout << dt_input <<endl;}

例 11. 2 用户定义 Date 数据类中对流类运算符 << 、 >> 函数重载

Page 24: 第 11 章   输入输出流类

重载操作符函数时应该注意以下几点 :

重载的操作符函数有两个参数。

如果重载的是输出操作符 << ,第一个参数是对流 ostream 类的引用,如果重载的是输入操作符>> ,第一个参数是对流 istream 类的引用。

第二个参数是要定义输入输出类的引用,也可以是此类的指针。

运算符重载必须定义为类的友元,因为左操作数必须是流类对象而不是输入 / 输出类的对象,不能使用隐式左操作数。

Page 25: 第 11 章   输入输出流类

#

查询

复杂程度

复杂数据、有查询

对象 - 关系数据库( O

RDB )

简单数据、无查询

文本文件

简单数据、无查询

面向对象数据库 (OOD

B)

简单数据、有查询

关系式数据库( RDB )

Page 26: 第 11 章   输入输出流类

11. 4 文件流与文件操作

11.4.1 C++ 标准库文件输入与输出标准的 C++ 库提供了文件输入输出功能,它们是以函数的形式给出的。这里将对一些常

用的函数如 fopen 、 fclose 、 fwrite 、 fread 等作简要说明。标准的 C 库对文件输入输出功能函数定义在 stdio.h 头文件中,并且定义了一个 FILE

型文件结构,在每一个文件被打开时,都有一个 FILE 型文件指针与之关联,以便保存文件的相关信息,完成文件的读写操作。

Page 27: 第 11 章   输入输出流类

对文件的操作一般分为三个步骤:

( 1 )使用文件打开函数对文件进行打开,并与文件指针建立关系 ;( 2 )利用文件指针和写文件、读文件函数对文件进行操作。( 3 )使用文件关闭函数,对文件关闭。

Page 28: 第 11 章   输入输出流类

1 打开文件函数 fopen完成文件操作第一步,可使用 fopen 函数,该函数定义为 : FILE *fopen( const char *filename, const char *mode ); 其中参数 filename 是文件名字符串, mode 为文件打开的模式。使用时注意 :1). 返回值是返回打开文件的指针,如果文件不存在或者不能找到文件, fopen 调用返 回空指针( NULL )表示为文件打开失败。 2). 参数 mode 可取以下值"r" 只读方式打开文件。"w" 写方式打开文件,如果文件已经存在,其文件中的内容被破坏。"r+" 读和写的方式打开。(文件必须已经存在,否则将导致异常)"w+" 读和写方式打开一空文件,如果该文件已经存在,其内容将被破坏。"a+" 为了读文件和附加新内容而打开文件。 "t" 以文本方式打开文件。 "b" 二进制的方式打开文件。

Page 29: 第 11 章   输入输出流类

2. 文件读写函数 fread 和 fwrite 完成第二步操作,就是要对文件进行读和写数据,一般常用 fread 读

文件函数和 fwrite函数 , 函数的使用格式为: size_t fread( void *buffer, size_t size, size_t count, FILE *stream ); size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );使用时注意 :( 1 ) fread 函数读文件返回文件数据记录的数目 ;( 2 ) fwrite 函数返回实际写入文件数据记录的数目 ;( 3 )参数 buffer 指向数据缓冲区。 fread 函数将读出的数据放在

缓冲区中供程序使用 ; fwrite 函数将写入文件的数据放在冲区中以便写入文件。( 4 ) size 为从文件读出和写入文件的字节数( 5 ) count 一次从文件读出数据的最大记录数和一次写入文件的最大

记录数。( 6 ) stream 文件结构指针。 fread 函数为打开文件的针 ; fwrite 函数

为把数据要写入 文件的指针。

Page 30: 第 11 章   输入输出流类

3 关闭文件函数 fclose 完成第三步操作可以使用 fclose ,其格式为 : int fclose( FILE *stream );// 关闭流文件 (fclose) int _fcloseall( void ); // 关闭所有的流 (_fcloseall) 使用时注意 : ( 1 ) fclose 函数返回值为 0 时表示文件成功关闭,否则返回值为非 0 。 ( 2 ) fcloseall 成功关闭所打开的文件时,函数返回值为关闭文件的总数。 ( 3 ) fclose 函数的参数为指向 FILE 结构体的指针。

Page 31: 第 11 章   输入输出流类

例 11. 3 打开一个名为 FREAD.OUT 的文件并写入 25 个字符 , 然后将从文件中读出的字符#include <stdio.h>void main(){ FILE *stream; char list[30]; int i, numread, numwritten; // 文本模式打开文件并写数据 if( (stream = fopen( "fread.out", "w+t" )) != NULL ) { for ( i = 0; i < 25; i++ ) list[i] = (char)('z' - i); numwritten = fwrite( list, sizeof( char ), 25, stream ); printf( "Wrote %d items\n", numwritten ); fclose( stream ); } else printf( "Problem opening the file\n" ); /* 读出 25 个字符 */ if( (stream = fopen( "fread.out", "r+t" )) != NULL ) { numread = fread( list, sizeof( char ), 25, stream ); printf( "Number of items read = %d\n", numread ); printf( "Contents of buffer = %.25s\n", list ); fclose( stream ); } else printf( "File could not be opened\n" );}输出:Wrote 25 itemsNumber of items read = 25Contents of buffer = zyxwvutsrqponmlkjihgfedcb

Page 32: 第 11 章   输入输出流类

11.4.2 文件输入输出流在 C ++ 中,对文件的输入输出操作提供了另一种操作方式,即流类库的文件操作,这些类是 ofstream 与 ifstream 文件输入输出流类。

其对文件操作也需要上述的三个步骤。

1. 文件的输出 文件的输出由 ofstream 完成,它由 ostream 类继承而来 ( 见图 11.2) ,并继承了它的操作,因此可以利用 ostream 重载的操作符 << 把数据写

入文件流中。进行文件输出时首先要创建文件输出流 ofstream 类的一个对象, ofstream 类的构造函数用于在不同情况下构造文件流。下面是 ofstream类造函数的定义 :

ofstream();ofstream(const char FAR *,int=ios::out,int=filebuf::openprot);

Page 33: 第 11 章   输入输出流类

( 1 )文件的打开第一个构造函数用于构造一个不带参数的流 , 如果需要可以在用它的 open 函数打开一个文件 , 下面是 open 函数的定义 :void open(const signed char_FAR *,int=ios::in,int=filebuf::openprot);它需要三个参数,第一个参数为字符串,为打开文件的文件名;第二个参数为文件模式 , 缺省为 ios::out ,表示为输入打开,其它文

件模式见表 11.4; 第三个参数为文件的保护方式它们有三种取值 0 表示普通文件、 1 表示只读文件、 2 表示隐含文件、 4 表示系统文件、 8 表示文档位格式。例如对打开一个 test1.dat 文件可用如下语句: ofstream afile(); afile.open("test1.dat"); 或 afile.open("test1.dat" , ios::out|ios::binary)

第二个构造函数可以在创建文件时通过第一个参数直接指定文件名。第二个参数、第三个参数同上述 open 函数。 对打开一个 test1.dat 文件可用如下语句: ofstream afile("test1.dat"); ofstream afile("test1",ios::noreplace); ofstream afile("test1",ios::append); ofstream afile("test1",ios::out|ios::binary);

Page 34: 第 11 章   输入输出流类

表 11.4 文件模式 模式 功能说明

Ios:app 追加数据 , 总是加在源文件的尾部

Ios::ate 在打开的文件上找到文件尾

Ios::in 为输入打开文件 ( 默认对 ifstream 适用 )

Ios::out 为输出打开文件 ( 默认对 ofstream 适用 )

Ios::binary 打开二进制文件

Ios::trunc 如文件存在则消去原内容

Ios::nocreate 如文件不存在 , 打开失败

Ios::noreplace 如文件存在 , 打开失败 , 除非设置了 ate 和 app

Page 35: 第 11 章   输入输出流类

2). 文件的写入数据函数 ofstream 类是从 ostream 类继承而来,因而可以使用 ostream 类的写数据的函数和操作

符把数据写入文件,操作符函数在前面已经介绍,这里实现写数据的函数是 :class _CRTIMP ostream : virtual public ios {……public: // 写入字符文件 inline ostream& put(char);

ostream& put(unsigned char); inline ostream& put(signed char); // 写入字符串 str 的内容到文件

ostream& write(const char *,int); inline ostream& write(const unsigned char

*,int); inline ostream& write(const signed char *,i

nt); // 移动输出文件的位置指针

ostream& seekp(streampos); ostream& seekp(streamoff,ios::seek

_dir); // 取当前输出文件位置指针的值

streampos tellp(); ……. }

Page 36: 第 11 章   输入输出流类

3). 文件的关闭函数 ofstream 类也是从 fstreambase 类继承的,可以使用 fstreambase 类的 close(); 来关闭文件。

Page 37: 第 11 章   输入输出流类

2. 文件的输入文件的输入由类 ifstream 完成 , 它由 iostream 和 fstreamb

ase 类继承而来 , 并继承了它的操作符 >> 函数和文件打开,从文件中读数据、关闭文件的函数。 ifstream 也提供了构造函数:

ifstream();ifstream(const cahr_FAR *,int=ios::in,int=filebuf::openprot)

;

Page 38: 第 11 章   输入输出流类

1). 文件的打开 第一个构造函数用于构造一个不带参数的流 , 如果需要可以在用它的 open 函数打开一个文件 , 下面是 open 函数的定义 : void open(const signed char_FAR *,int=ios::in,int=filebuf::openprot);它和第二构造函数的使用同文件的输入中的文件打开。 2). 文件的数据读出函数 可以使用 istream 类的写数据的函数和操作符把数据写入文件,操作符函数在前面已经介绍,这里实现写数据的函数是 :class _CRTIMP istream : virtual public ios {……public: // 读取文件数据到字符串内 inline istream& get(char *,int,char ='\n'); inline istream& get(unsigned char *,int,char ='\n'); inline istream& get(signed char *,int,char ='\n'); // 读取文件数据到字符内 istream& get(char &); inline istream& get(unsigned char &); inline istream& get( signed char &);istream& get(streambuf&,char ='\n'); // 读取文件一行数据到字符串内 inline istream& getline(char *,int,char ='\n'); inline istream& getline(unsigned char *,int,char ='\n'); inline istream& getline(signed char *,int,char ='\n'); inline istream& ignore(int =1,int =EOF); // 读取文件数据到字符串内 istream& read(char *,int); inline istream& read(unsigned char *,int); inline istream& read(signed char *,int); int gcount() const { return x_gcount; } int peek(); istream& putback(char); int sync(); // 移动输入文件指针位置 istream& seekg(streampos);istream& seekg(streamoff,ios::seek_dir);// 读取当前输入文件指针位置的值streampos tellg();……

}

Page 39: 第 11 章   输入输出流类

3). 文件的关闭函数ifstream 类也是从 fstreambase 类继承的,可以使用 fstreambase 类的 close(); 来关闭文件。

Page 40: 第 11 章   输入输出流类

例 11. 4 使用 istream 和 ostream 类的文件操作函数把一个文件 file.in 的内容拷贝到另一个文件 file.out 。#include <iostream.h>#include <fstream.h>#include <process.h>void main(){ char ch;ifstream fin(“file.in”); // 创建一个输入流 , 并和输入文件 file.in 联系ofstream fout(“file.out”);// 创建一输出流 , 并和输出文件 file.out 联系if(!fin){ cerr<<”Cannot open file file.in”;exit(-1); // 如果原文件出错 , 显示信息并退出 }if (!fout){cerr<<”Can’t open file file.out”;exit(-1); // 如果目的文件出错 , 显示信息并退出}while (fout&&fin.get(ch))fout.put(ch);

}

Page 41: 第 11 章   输入输出流类

例 11. 5 利用 istream 和 ostream 类的操作符对点数据进行文件操作 , 从键盘上输入两个点的坐标,把它保存到磁盘文件上,并从磁盘上读出数据,写到显示器上。

#include <stdio.h>#include <conio.h>#include <istream.h>#include <ostream.h>#include <fstream.h>#include <process.h>class Point {protected: int X; int Y;public: Point(int x,int y){X=x;Y=y;} friend ostream& operator<<(ostream& os, Point& aPoint); friend istream& operator>>(istream& is, Point& aPoint);};ostream& operator<<(ostream& os,Point& aPoint){os<<"("<<aPoint.X<<","<<aPoint.Y<<")";return os; // 返回流的引用}istream& operator>>(istream& is, Point& aPoint){is>> aPoint.X>> aPoint.Y;return is; // 返回流的引用}int main(){ int x,y;ofstream writefile("cstest.sav"); // 创建一个文件流if (!writefile) // 如果创建失败 , 退出{ cout <<"Can't open file";exit(-1);}cout <<"input the x 、 y with blank seperated:"; // 标准流输出提示cin>>x>>y; // 标准输入流输入数据Point Point1(x,y); // 创建点对象cout<<"input x 、 y of another point:"; // 提示输入另一个点 cin>>x>>y; // 标准输入流输入数据Point Point2(x,y); // 创建点对象writefile<<Point1; // 把第一个点存入文件writefile<<Point2; // 把第二个点存入文件writefile.close();ifstream readfile("ctest.sav"); // 创建一个输入文件流if(!readfile) // 如果创建失败 , 退出 ,{ cout<<"Can't open file";exit(-1);}readfile>>Point1>>Point2; // 把文件的数据读入点对象cout<<Point1<<endl; // 将第一个点对象写在显示器上cout<<Point2<<endl; // 将第二个点对象写在显示器上return 0;

}

Page 42: 第 11 章   输入输出流类