第 9 章 流类库与输入 / 输出

63
第9第 第第第第第第 / 第第 第9第 第第第第第第 / 第第 第第第第I/O 第第第第第第 第第第第第第第第 第第第第第第第第第第 第第第第第第第第第第第 第 ,,,, 第第第第第第第第第第第 第第第第第第第 ,。 第第第第第第第第第第第第 第第第 第第第第第第第第第第第第第 、、 ; 第第第第第第 / 第第第第第第第第第

Upload: kieve

Post on 10-Jan-2016

115 views

Category:

Documents


5 download

DESCRIPTION

第 9 章 流类库与输入 / 输出. 教学内容: I/O 流类库的功能,常用的读写操作,格式化输入输出操作,插入符和提取符的重载,磁盘文件的输入和输出操作,字符串流操作。 教学要求: 理解文件流的打开、读写、关闭方法以及设备文件的使用 ; 掌握基本输入 / 提取操作和格式控制。. 第 9 章 流类库与输入 / 输出. 9.1 输入 / 输出标准流类 9.2 文件流类 9.3 串流类 9.4 控制符. 9.1 输入 / 输出标准流类. 9.1.1 输入 / 输出流的概念 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

教学内容:I/O 流类库的功能,常用的读写操作,格式化输入输出操作,

插入符和提取符的重载,磁盘文件的输入和输出操作,字符串流操作。

教学要求:理解文件流的打开、读写、关闭方法以及设备文件的使用 ;

掌握基本输入 / 提取操作和格式控制。

Page 2: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

9.1 输入/输出标准流类

9.2 文件流类

9.3 串流类

9.4 控制符

Page 3: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

9.1 输入 / 输出标准流类

9.1.1 输入 / 输出流的概念 C++ 语言中没有输入 / 输出语句。 C++ 的 I/O 是以

字节流的形式实现的,每一个 C++ 编译系统都带有一个面向对象的输入 / 输出软件包,这就是 I/O 流类库。其中,流是 I/O 流类的中心概念。到目前为止,我们一直在使用它。

Page 4: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

所谓流,是指数据从一个对象流向另一个对象。在 C++ 程序中,数据可以从键盘流入到程序中,也可以从程序中流向屏幕或磁盘文件,把数据的流动抽象为“流”。流在使用前要被建立,使用后要被删除,还要使用一些特定的操作从流中获取数据或向流中添加数据。从流中获取数据的操作称为提取操作,向流中添加数据的操作称为插入操作。

Page 5: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

流实际上就是一个字节序列。在输入操作中,字节从输入设备 ( 如键盘、磁盘、网络连接等 ) 流向内存;在输出操作中,字节从内存流向输出设备 ( 如显示器、打 印 机 、 磁 盘 、 网 络 连 接 等 ) 。 如 图 9-1 所 示 。

在 C++ 语言中,针对流的特点,提供了如图 9-2 所示的层次结构来描述流的行为,并给出了 I/

O 流类库的操作。

Page 6: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

Page 7: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

图 9-2 输入 / 输出流类层次图

Page 8: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

表 9-1 I/O 流类列表

Page 9: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

9.1.2 输入 / 输出标准流类1 .标准流的设备名由表 9-1 可见, I/O 流的标准头文件是 iostream.h 。其中,

ostream 类通过其派生类 ostream_withassign 支持以下预先定义的流对象:

cout :标准输出。默认设备为屏幕。 cerr :标准错误输出。没有缓冲,发送给它的内容

立即被输出,默认设备为屏幕。

Page 10: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

clog :标准错误输出。有缓冲,当缓冲区满时被输出,默认设备为打印机。

而 istream 类通过其派生类 istream_withassign 支持预先定义的对象。

cin :标准输入。默认设备为键盘。

Page 11: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

2 .原理cout 是 ostream 类的全局对象,它在头文件 iostream.h 中的

定义如下:ostream cout(stdout) ; // 这里, stdout 作为该对象构造时

的参数对应每种基本数据类型, ostream 类都存在友元,它们都在 iostream.h 中声明。例如:

ostream& operator<<(int n);

ostream& operator<<(float f);

ostream& operator<<(const char*psz);

//...

Page 12: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

如语句: cout<<"How old are you? ";

cout 是类 ostream 的对象, << 是插入运算符,右面是 char* 类型,所以,应该匹配上面第三个操作符。它将整个字符串输出,并返回 ostream 流对象的引用。

同理, cin 是 istream 的全局对象, istream 类也存在友元。例如:

istream& operator>>( int &n);

istream& operator>>( float &f);

istream& operator>>( char*psz);

//...

Page 13: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

9.2 文件流类

fstream 、 ifstream 和 ofstream 是文件流类,在头文件 fstream.h 中定义。其中, fstream 是 ofstream 和 if

stream 多重继承的子类。文件流类不是标准设备,没有 cout 那样预先定义的全局对象。文件流类支持对磁盘文件的操作。要定义一个文件流类对象,须指定文件名和打开方式。

Page 14: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

类 ofstream 用于执行文件输出,该类有以下几个构造函数:

ofstream::ofstream( filedesc fd );

ofstream::ofstream( filedesc fd, char*pch, int nLength );

ofstream::ofstream( const char*szName,

int nMode = ios::out,

int nProt = filebuf::openprot );

Page 15: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

类 ifstream 用于执行文件输入,该类有以下几个构造函数:ifstream::ifstream( filedesc fd );

ifstream::ifstream( filedesc fd, char*pch, int nLength );

ifstream::ifstream( const char*szName,

int nMode = ios::in,

int nProt = filebuf::openprot );

Page 16: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

其中最常用的都是最后一个构造函数。该函数有三个参数,第一个参数是指向要打开的文件名的字符串,后两个参数指定文件的打开模式。文件打开模式的具体标志见表 9-2 。可以用按位 OR ( | )运算符组合这些标志,它们作为枚举器定义在 ios 类中。

Page 17: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

表 9-2 文件打开模式

Page 18: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

打开一个输出文件,用于在文件尾添加数据 打开一个现存文件 ( 用于输入或输出 ) 并查找到结

尾 打开一个输入文件。对于一个 ofstream 文件,使

用 ios::in 作为一个 openmode ,可避免删除一个现存文件中现有的内容

打开一个文件,用于输出。对于所有 ofstream 对象,此模式是隐含指定的

如果一个文件存在,则打开它;否则该操作失败

Page 19: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

如果一个文件不存在,则作为新文件打开它;如果文件已存在,则该操作失败

打开一个文件。如果它已经存在,则删除其中原有的内容。如果指定了 ios::out ,但没有指定 ios::ate 、ios::app 和 ios::in ,则隐含为此模式

以二进制模式打开一个文件 ( 默认是文本模式 )

Nprot 是文件保护方式,它的标志如表 9-3 。

Page 20: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

表 9-3 文件保护方式

Page 21: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

【例 9-1】 向文件 myfile 中写入一些信息。#include<fstream.h>

void main( )

{

ofstream fc("c:\\temp\\myfile");

fc<<"Constructs an ofstream object.\n"

<<"All ofstream constructors construct a filebuf object. \

n";

}

Page 22: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

注意: ① 这里的文件名要说明其路径,要使用双斜杠,因为 C++ 编译器理解单斜杠为字符转换符。

② 在文件打开时,匹配了构造函数 ofstream::ofstre

am(char*) ,只需要一个文件名,其它为默认。打开方式默认为 ios::out | ios::trunc ,即该文件用于接受程序的输出。如果该文件已存在,则其内容必须先清除,否则就新建。

Page 23: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

如果要检查文件是否打开,则须判断成员函数 fail( ):

#include <fstream.h>

void func( )

{

ofstream fc("myfile");

if(fc.fail( )) //fail( )= =1

{

cerr<<"error opening file\n";

return;

}

fc<<"...";

Page 24: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

}

若要打开一个输入文件,则有//...

ifstream fc("myfile",ios::nocreate);

//...

当然,也可以通过检查 fc.fail( ) 来确定文件打开是否出错。如果要打开一个同时用于输入和输出的文件,则有//...

fstream fc("myfile",ios::in | ios::out);

//...

Page 25: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

9.3 串流类

strstream 、 istrstream 和 ostrstream 是串流类,在头文件 strstrea.h 中定义。其中, strstream 是 istrstream

和 ostrstream 多重继承的子类。同样,串流类也不是标准设备,它没有 cout 那样预先定义的全局对象。串流类允许将 fstream 类定义的文件操作应用于存储区中的字符串,即将字符串看作为设备。要定义一个串流类对象,须提供字符数组和数组大小。

Page 26: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

类 ostrstream 用于执行串流输出,该类有以下几个构造函数:

ostrstream( );

ostrstream( char*pch, int nLength, int nMode = ios::o

ut );

其中比较常用的是第二个构造函数,它有三个参数。第一个参数指出字符数组,第二个参数说明数组的大小,第三个参数指出打开方式。

Page 27: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

类 istrstream 用于执行串流输入,该类有以下几个构造函数:

istrstream( char*pch );

istrstream( char*pch, int nLength );

这两个构造函数都比较常用。 Char*pch 参数指出了字符数组, int nLength 参数说明数组的大小。当 nL

ength 为 0 时,表示把 istrstream 类对象连接到由 pch

指向的以空字符结束的字符串。

Page 28: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

例如,下面的程序代码定义一个串流类对象,并对其进行输入操作:

char str[50]="How are you!\n";

char a;

istrstream ss(str);

ss>>a;

cout<<a<<endl;

输出结果为 H

Page 29: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

【例 9-2】 使用串流输入对字符串中的数据进行解读。#include<iostream.h>

#include<strstrea.h>

char *ioString(char*);

void main( )

{

char *str="100 123.456";

char *Buf0=ioString(str);

cout<<Buf0<<endl;

}

Page 30: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出char *ioString(char *pString)

{

istrstream inS(pString,0); // 以 ios::in 方式int iNumber;

float fNumber;

inS>>iNumber>>fNumber; // 从串流中读入一个整数和浮点数char*Buf1=new char[28];

ostrstream outS(Buf1,28);

outS<<"iNumber="<<iNumber

<<",fNumber="<<fNumber<<endl;

return Buf1;

Page 31: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

}

程序运行结果为 iNumber=100,fNumber=123.456

分析:在函数 ioString( ) 中,以 pString 为输入设备,先定义一个输入串流对象 inS ,从中输入一个整数和一个浮点数。再开辟一个字符串空间作为输出设备,定义一个输出串流对象 outS ,将从输入设备输入的两个变量的值输出。

Page 32: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

9.4 控制符9.4.1 使用流对象的成员函数【例 9-3】 使用 width成员函数控制输出宽度。 #include <iostream.h>

void main( )

{

double values[ ]={1.44,36.47,625.7,4096.24};

for(int i=0;i<4;i++)

{

Page 33: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

cout.width(10);

cout<<values[i]<<'\n';

}

}

程序运行结果为 1.44

36.47

625.7

4096.24

Page 34: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

此例子在一列中以至少 10 个字符宽按右对齐方式输出数据。从程序的输出结果可以看到,在少于 10 个字符宽的数值前加入了引导空格。

空格是默认的填充符,当输出的数据不能充满指定的宽度时,系统会自动以空格填充。另外,还可以使用 fill成员函数为已经指定宽度的域设置填充字符的值。为了用星号填充数值列,我们可以将例 9-3 中的 f

or循环修改如下:

Page 35: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

for(int i=0;i<4;i++)

{

cout.width(10);

cout.fill('*');

cout<<values[i]<<endl;

}

其输出结果为******1.44

*****36.47

*****625.7

***4096.24

Page 36: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

9.4.2 使用控制符C++ 的输入 / 输出流类库提供了一些控制符,可以直

接嵌入到输入 / 输出语句中来实现对 I/O 格式的控制。它的优点是程序可以直接将控制符插入流中,而不必单独调用。表 9-4 中列出了常用的 I/O 流类库控制符。

Page 37: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

表 9-4 常用的 I/O 流类库控制符

Page 38: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

Page 39: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

【例 9-4】 使用 setw 控制符指定宽度。#include<iostream.h>

#include<iomanip.h>

void main( )

{

double values[ ]={1.44,36.47,625.7,4096.24};

char *names[ ]={"Rose","John","Alice","Mary"};

for(int i=0;i<4;i++)

Page 40: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

cout<<setw(6)<<names[i]<<setw(10)<<values[i]<<endl;

}

width成员函数在头文件 iostream.h 中说明。 如果带参量使用 setw(n) 或任何其它控制符,还必须包括头文件 iomanip.h 。在输出中,字符串输出在宽度为 6 的域中,整数输出在宽度为 10 的域中。程序运行结果为

Rose 1.44

John 36.47

Alice 625.7

Mary 4096.24

Page 41: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

setw 和 width 都不截断数值。如果一个数值需要比 set(n)确定的字符数更多的字符,则该值将使用它所需要的所有字符。当然,还要遵守该流的精度设置。 s

etw 和 width仅影响紧随其后的域,即使用 setw 和 widt

h 设置的间隔方式并不保留其效力。在一个域输出完后,域宽度恢复成它的默认值 (必要的宽度 ) ,但其它流格式选项保持有效直到发生改变。

Page 42: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

例如,下面的程序代码://...

cout <<setiosflags(ios::right) // 设置为默认的右对齐方式,

<<setw(5)<<1

<<setw(5)<<2

<<setw(5)<<3<<endl ;cout <<setiosflags(ios::left) // 设置成左对齐方式

Page 43: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

<<setw(5)<<1

<<setw(5)<<2

<<setw(5)<<3<<endl ; cout<<resetiosflags(ios::left) // 关闭左对齐标志 //...

这段程序代码中,是通过使用带参数的 setiosflags

控制符来设置左、右对齐,参数是 ios::left 和 ios::right

枚举器。

Page 44: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

该枚举器定义在 ios 类中,因此,引用时必须包括ios:: 前缀。这里需要用 resctiosflags 操纵符关闭左、右对齐标志。 setiosflags 不同于 width 和 setw ,它的影响是持久的,直到用 resetiosflags 重新恢复默认值时为止。

这段程序代码的输出结果为 1 2 3

1 2 3

常用控制符和流格式控制成员函数如表 9-5 所示。

Page 45: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

表 9-5 常用控制符和流成员函数

Page 46: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

9.5 输入 / 输出成员函数

9.5.1 使用成员函数输入1 . getline( ) 函数在程序使用 cin 输入时, cin 用空白符和行结束符将

各个值分开。有时候输入可能需要读取一整行文本并且分开不同的域,为此,我们可以使用 getline成员函数。其函数原型如下:

istream&getline( char*pch, int nCount, char delim =

'\n' );

Page 47: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

其中,第一个参数是字符数组,用于放置读取的文本;第二个参数是本次读取的最大字符个数;第三个参数是分隔字符,作为读取一行结束的标志。

getline成员函数的功能是允许从输入流中读取多个字符 ( 包括空白字符和行结束符 ) ,并且允许指定输入终止字符 ( 默认值是换行字符 ) 。在读取完成后,从读取的内容中删除该终止字符。

Page 48: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

【例 9-5】 为输入流指定一个终止字符。 本程序连续读入一串字符,直到遇到字符 t 时停止,

字符个数最多不超过 99 个。程序中的 t 是大小写敏感的。 #include<iostream.h>

void main( )

{

char line[100];

cout<<"Type a line terminated by 't'"<<endl;

cin.getline(line,100,'t');

cout<<line<<endl;

}

Page 49: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

2 . get( ) 函数在输入时,有些时候需要执行每次只输入单个字符的

操作,我们可以使用 get( )成员函数来完成。 get( ) 函数的格式如下:

char istream::get( );

【例 9-6】 循环读入字符,直到键入一个 y 字符,或遇到文件尾。

#include<iostream.h>

void main( )

{

char letter;

while(!cin.eof( ))

Page 50: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

{

letter=cin.get( );

if(letter=='y')

{

cout<<"'y'be met!";

break;

}

cout<<letter;

}

}

Page 51: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

get( ) 函数还有一种形式可以输入一系列字符,直到输入流中出现结束符或所读字符个数已达到要求读的字符个数。这时, get( ) 函数的函数原型如下:

istream&istream::get(char*,int n,char delim='\n');

Page 52: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

例如,下面程序输入一系列字符,将前 24 个字符输出。 #include <iostream.h>

void main( )

{

char line[25];

cout << " Type a line terminated by carriage return\n>";

cin.get( line, 25 );

cout << ' ' << line;

}

Page 53: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

9.5.2 使用成员函数输出【例 9-7】 使用 put( )成员函数,在屏幕上显示字

母表中的字母。 #include<iostream.h>

void main( )

{

char letter;

for(letter='A';letter<='Z';letter++)

cout.put(letter);

}

Page 54: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

程序运行结果为ABCDEFGHIJKMNOPQRSTUVWXYZ

也可以像下面那样在一条语句中连续调用 put( ) 函数:cout.put('A').put('\n');

该语句在输出字符 A 后输出一个新换行符。还可以用 ASCII码值表达式调用 put( ) 函数:cout.put(65);

该语句也输出字符 A 。

Page 55: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

9.6 用户自定义类型的输入 / 输出

【例 9-8】 用户自定义的插入运算符和提取运算符。 #include<iostream.h>

class PhoneNumber

{

private:

char nationCode[4];

char areaCode[4];

char phoneCode[8];

Page 56: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

public:

friend ostream& operator<<(ostream&,PhoneNumber&);

friend istream& operator>>(istream&,PhoneNumber&);

};

ostream& operator<<(ostream& output,PhoneNumber& nu

m)

{

output<<"("<<num.nationCode<<")"

<<num.areaCode<<"-"<<num.phoneCode;

return output;

Page 57: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

}

istream& operator>>(istream& input,PhoneNumber& num)

{

input.ignore( ); //跳过 (input.getline(num.nationCode,4);

input.ignore( ); //跳过 )input.getline(num.areaCode,4);

input.ignore( ); //跳过 -

input.getline(num.phoneCode,8);

return input;

Page 58: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

}

void main( )

{

PhoneNumber phone;

cout<<"Enter a telephone number in the"

<<" form(086)029-5261111\n";

cin>>phone;

cout<<"The phone number entered was:\n"

<<phone<<endl;

}

Page 59: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

程序运行结果为 输入:( 086 ) 029-1234567

The phone number entered was:

( 086 ) 029-1234567

该程序为处理用户自定义的电话号码类 PhoneNum

ber 的数据重载了这两个运算符。另外,该程序假定电话号码的输入是正确的。

Page 60: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

提取运算符的参数是对 istream 对象的引用和对自定义类型对象的引用,返回对 istream 对象的引用。在该程序中,重载的提取运算符用于把形如 (086)029-526

1111 的电话号码输入到 PhoneNumber 类型的对象中。运算符函数分别将电话号码的三个部分分别读到被引用的 PhoneNumber 对象的成员 nationCode 、 areaCode

和 phoneCode 中 ( 在运算符函数中,被引用对象是 nu

m ;在 main 函数中,被引用对象是 phone) 。

Page 61: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

调用成员函数 ignore( )去掉了括号和破折号。运算符函数返回 istream& 类型的引用 input 。通过返回对流引用,我们可以在一条语句中执行完对类 PhoneNumbe

r 的对象的输入操作后,继续执行对类 PhoneNumber

的其它对象或其它数据类型的输入操作。如两个 Phone

Number 对象可以按下列方式输入: cin>>phone1>>phone2;

Page 62: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

插入运算符的两个参数是对 ostream 对象的引用和对自定义类型(本例中为 PhoneNumber )的对象的引用,返回对 ostream 对象的引用。在该程序中,重载的插入运算符按输入格式显示类 PhoneNumber 的对象。该运算符函数将电话号码各部分显示为字符串,因为它们是以字符串格式存储的(类 istream 中的成员函数getline 在结束输入后存储一个空字符)。

Page 63: 第 9 章  流类库与输入 / 输出

第 9 章 流类库与输入 / 输出

重载的运算符函数在类 PhoneNumber 中被声明为友元函数。为了能够访问类中非公有成员,重载的输入和输出运算符必须被声明为类的友元。

C++允许为用户自定义类型增加新的输入 / 输出能力,而无需修改类 ostream 或 istream 中的声明和私有数据成员。这大大提高了 C++ 的可扩展性。