第8章 I/O流 8.1 C++流的概念 8.2 C++的输入输出 8.3 文件流与文件操作 8.4 重载插入运算符和提取运算符

Slides:



Advertisements
Similar presentations
面向对象程序设计 QQ群: Object-Oriented Programming 汽车学院.
Advertisements

第11章 输入输出流类.
流类库与输入/输出 输入/输出标准流类 文件流类 串流类 输入/输出成员函数 用户自定义类型的输入/输出.
13.1 C++的输入和输出 13.2 标准输出流 13.3 标准输入流 13.4 文件操作与文件流 13.5 字符串流
C语言实验 第一课 标题:学号+姓名.
C++中的声音处理 在传统Turbo C环境中,如果想用C语言控制电脑发声,可以用Sound函数。在VC6.6环境中如果想控制电脑发声则采用Beep函数。原型为: Beep(频率,持续时间) , 单位毫秒 暂停程序执行使用Sleep函数 Sleep(持续时间), 单位毫秒 引用这两个函数时,必须包含头文件
目标 运用File类进行文件操作 理解流,标准输入/输出流的概念
C++的檔案處理 綠園.
複習 struct score_Type{ int chinese,english; }; struct my_Type{
C File System.
Hadoop I/O By ShiChaojie.
计算概论 第二十一讲 文件操作 北京大学信息学院.
第七章 I/O流.
第十一章 文件操作 文件的概念 文件的读写 主讲:李祥 时间:2015年10月.
File Processing Chapter 17
C 程式設計— 檔案處理 台大資訊工程學系 資訊系統訓練班.
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
辅导课程六.
第9章 C++的文件操作 “文件”,一般是指内存以外的存储介质上一批数据的集合。C++在语言层次上提供了文件操作的一系列函数用于完成文件的操作,打开、关闭文件,读取、写入文件数据等操作。 1。字符文件与二进制文件 字符文件:又称ASCII文件或文本TEXT文件,它是以一个字节存放一个ASCII码,代表一个字符。例如,32767需要使用5个字节表示,即:
第14章 标准库和输入输出流 14.1 标准库概述 14.2 流 14.3 输入输出流 14.4 格式化I/O 14.5 文件处理
第十二章 文件 12.1 C文件概述 文件:存储在外部介质上数据的集合,是操作系统数据管理的单位 文件分类 按文件的逻辑结构: 按存储介质:
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
文件读写实践 广州创龙电子科技有限公司 01 广州创龙电子科技有限公司
檔案 將資料存入磁碟或由磁碟取出資料的方式, 稱為檔案存取處理。 C語言的檔案處理 C++語言的檔案處理.
程式設計 博碩文化出版發行.
第八章 文件 引述 输入输出流和文件概述 文件操作 流的格式化输出 程序举例 本章小节.
7.1 C++的输入和输出 7.2 标准输出流 7.3 标准输入流 7.4 文件操作与文件流 7.5 字符串流
第13章 输入输出流 王雪晶.
THE C PROGRAMMING LANGUAGE
第10章 文件操作.
Linux 文件操作——系统调用和标准 IO 库
第9章 文件 本章导读 本章主要知识点 《 C语言程序设计》 (Visual C++ 6.0环境)
第九章 C++的I/O流库 9.1 流 9.2 磁盘文件 9.3 程序举例.
第5章 文件.
第9章 文件操作 文件 使用文件的目的 操作系统管理数据的基本单位 存储在外存储器上的数据的集合
第八章 文件 引述 输入输出流和文件概述 文件操作 流的格式化输出 程序举例 本章小节.
C++语言程序设计 第十一章 流类库与输入/输出.
用event class 从input的root文件中,由DmpDataBuffer::ReadObject读取数据的问题
目录 11.1 文件的种类 11.2 文件指针和文件内部的位置指针 11.3 文件的操作 11.4 文件的打开与关闭
第七章 操作符重载 胡昊 南京大学计算机系软件所.
Java语言程序设计 清华大学出版社 第8章 输入输出流(1).
第 14 章 輸出與輸入.
第十三讲 文件流与 输出输入重载.
第9章 文件 学习目的与要求: 熟练掌握文件指针的使用 掌握与文件相关的函数 能够利用文件相关函数实现各种操作.
C语言程序设计.
第14章 输入输出与文件 输入输出是指程序与外部设备交换信息 C++把输入输出看成是一个数据流 输入流:外围设备流向内存的数据
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
一、文件的基本概念 第十三章 文 件 所谓“文件”是指一组相关数据的有序集合。 这个数据集有一
第7章 输入/输出流 文件和I/O流概述 标准I/O流的对象及其成员函数 文件流.
手机移动设备嵌入式C++ 第七章 C++的I/O流库.
第 11 章 输入/输出流 11.1 输入/输出流概述 11.2 标准输入/输出流 11.3 输入/输出格式控制 11.4 文件输入/输出
本节内容 随机读取 视频提供:昆山爱达人信息技术有限公司.
姚金宇 MIT SCHEME 使用说明 姚金宇
C++的檔案處理 綠園.
C语言程序设计 第一章 数据类型, 运算符与表达式 第二章 顺序程序设计 第三章 选择结构程序设计 第四章 循环控制 第五章 数组.
C標準輸出入函數庫 與 作業系統.
第十一章 IO流与文件系统 丘志杰 电子科技大学 计算机学院 软件学院.
第2章 基本数据及其运算 本章学习的目标: 1、掌握基本数据的各种表示,基本数据常数的书写方法;
C++语言程序设计 C++语言程序设计 第二章 基本数据类型与表达式 第十一组 C++语言程序设计.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
C/C++基礎程式設計班 C++: 物件的使用、參考、重載函式 講師:林業峻 CSIE, NTU 3/28, 2015.
第1章 C++面向对象程序设计要点 1.1 函数和函数参数 1.2 输入输出   1.3 类 1.4 抽象类型和模板.
第13章 文 件.
_08文件操作 本节课讲师——void* 视频提供:昆山爱达人信息技术有限公司 官网地址:
C 程式設計— 檔案處理 台大資訊工程學系 資訊系統訓練班.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
第七章 文件 7.1 文件的基本概念 7.2 文件类型指针 7.3 文件的打开与关闭 7.4 文件的读/写 7.5 文件的随机读/写
使用Fragment 本讲大纲: 1、创建Fragment 2、在Activity中添加Fragment
第十四讲 文件流与 输出输入重载.
Presentation transcript:

第8章 I/O流 8.1 C++流的概念 8.2 C++的输入输出 8.3 文件流与文件操作 8.4 重载插入运算符和提取运算符 8.3 文件流与文件操作 8.4 重载插入运算符和提取运算符 8.5 编程实例

8.1 C++流的概念 C++流是指信息在内存与外部设备之间传递(流动)的过程。 C++流程及以下概念: l 标准I/O流:内存与标准输入输出设备之间信息的传递; l 文件I/O流:内存与外部文件之间信息的传递; l 字符串I/O流:内存变量与表示字符串流的字符数组之间信息的传递。

每一种I/O流都分为输入、输出和既输入又输出三种流动方式。各流动方式的流动方向如下: l 输入:从外部向内存变量流动; l 输出:从内存变量向外部流动; l 既输入又输出:内存和外部之间允许双向流动。 在C++流类库中定义有各种流类供用户直接使用,它们分别包含在不同的头文件中:

l iostream.h包含ios, istream, ostream, iostream等; l fstream.h包含ifstream, ofstream, fstream及iostream.h中的所有内容; l strstrea.h包含istrstream, ostrstream, strstream及iostream.h中的所有内容。 流类库员列表如表8.1所示。

表8.1 流类库成员列表 流类分类 流类名称 流 类 作 用 流基础类 ios 所有流类的父类,保存流的状态并处理错误 输入流类 表8.1 流类库成员列表 流类分类 流类名称 流 类 作 用 流基础类 ios 所有流类的父类,保存流的状态并处理错误 输入流类 istream 输入流基础类,将流缓冲区中的数据作格式化和非格式化之间的转换并输入 ifstream 文件输入流类 istream_withassign cin输入流类,即操作符>>输入流 istrstream 串输入流类

输出流类 ostream 输出流基础类,将流缓冲区中的数据作格式化和非格式化之间的转换。并输出 ofstream 文件输出流类 ostream_withassign Cout、cerr、clog的输出流类,即操作符<<输出流 ostrstream 串输出流类 文件流类 fstreambase 文件流基础类 串流 strstreambase 串流基础类 输入/输出流类 iostream 多目的输入/输出流类的基础类 fstream 文件流输入/输出类 strstream 串流输入/输出类

在iostream.h 头文件中定义有cin、cout和cerr等流类对象,分别表示标准输入设备键盘、标准输出设备显示器和保存错误信息的设备显示器。标准设备见表8.2。 表8.2 标准设备数 C++名字 设备 C中的名字 默认的含义 cin cout cerr clog 键盘 屏幕 打印机 stdin stdout stderr stdprn 标准输入 标准输出 标准错误

8.2 C++的输入输出 输入/输出流可以从文件或设备中读出或写入数据,C++运行库提供了两种输入/输出功能: (1) 把数据作为单字符流处理。可以处理简单的数据,也可以处理复杂的数据结构。 (2) 直接调用操作系统的底层功能实现输入/输出操作。 这两种输入/输出功能都含文件和标准的输入/输出功能。这里着重讨论流类的标准输入/输出、标准错误输出以及文件输入/输出。

8.2.1 标准输入输出 C++用istream_withassign类和ostream_withassign类来实现标准输入/输出功能。标准输入与输出是指读键盘的数据和将数据输出到屏幕。 在iostream.h文件中用以下两条语句定义cin和cout两个标准对象: istream_withassign cin ; ostream_withassign cout ;

8.2.2 标准错误输出cerr 当程序测试并处理关键错误时,若不希望程序的错误信息从屏幕显示,而是重定向到其它地方,这时使用cerr流显示信息。 例8.1 在除法操作不能进行时显示一条错误信息。 #include <iostream.h> void fn(int a,int b) {

if(b==0) cerr << "zero encountered. " << "The message can not be redirected." ; else cout << a /b << endl ; } void main() { fn(20,2); fn(20,0);

运行结果为: 10 zero encountered . The message can not be redirected . 说明:主函数第一次调用fn()函数时,没有碰到除0运算,于是得到文件的写内容10,第二次调用fn()函数时,碰到了除0运算,于是在屏幕上输出错误信息。写到cerr上的信息是不能被重定向的,因此它只能在屏幕上显示。

8.2.3 输入/输出格式控制 在程序中有时需要关心输入/输出的格式,C++提供了两种格式控制函数:一种是ios类中定义的格式控制成员函数;另一种是基于流对象的操纵函数。相比之下,使用操纵函数更为方便。 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 } 这些标志可以由ios类的成员函数flags()、setf()和unsetf()访问,也可以用操纵函数操作。

2. 操纵函数和操纵符 操纵函数分为带参数和不带参数两种。不带参数的操纵函数又叫操纵符,定义在头文件iostream.h中,带参数的操纵函数定义在头文件iomanip.h中。Fostream.h中的操纵符如表8.3所示。Jomanip.h中的操纵函数如表8.4所示。

表8.3 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 忽略输入流中的空格 end cout<<endl; 插入换行符,刷新流 ebds cout<<ends; 插入串最后的串结束符 flush cout<<flush; 刷新一个输入流

表8.4 iomanip.h中的操纵函数 操纵符 用 法 举 例 结 果 说 明 setprecision(int) cout<< setprecision(6) 输出精度为6位小数的浮点数 cin>> setprecision(15) 输入精度为15位小数的浮点数 setw(int) cout<<setw(6)<<var; 输出宽度为6的数据 cin>>setw(24)>>buf; 输入宽度为24的数据 setiosflags(long) cout<<setioflags(ios::hex| ios::uppercase) 指定数据输出的格式为十六进制格式且用大写字母输出 cin>>setioflags(ios::oct| ios::skipws) 指定数据输入的格式为八进制格式且跳过输入中的空白 reseriosflags(long) cout<< reseriosflags(ios::dec) 取消数据输出的十进制格式 cin>> reseriosflags(ios::hex) 取消数据输入的十六进制格式

例8.2 操纵符(函数)的使用。 #include<iomanip.h> void main() { int x=56; cout<<setw(6)<<x; cout<<setw(6)<<oct<<x; cout<<setw(6)<<hex<<x<<endl; cout.setf(ios::left); cout<<setw(6)<<dec<<x;

cout<<setw(6)<<oct<<x; cout<<setw(6)<<hex<<x<<endl; cout.unsetf(ios::left); cout<<setw(6)<<dec<<x; } 运行结果为: 56 70 38

8.3 文件流与文件操作 8.3.1 标准库文件函数输入/输出 8.3 文件流与文件操作 8.3.1 标准库文件函数输入/输出 标准C++兼容C语言的文件输入输出功能,它们是以函数的形式给出的。常用的文件输入/输出函数有fopen、fclose、fwrite和fread等。 标准的C库文件输入输出函数定义在stdio.h头文件中,并且定义了一个FILE型文件结构。

在每一个文件被打开时,都有一个FILE型文件指针与之关联,以便保存文件的相关信息,完成文件的读写操作。 对文件的操作一般分为3个步骤: l 使用文件打开函数打开文件,并与文件指针建立关系; l 利用文件指针和写文件、读文件函数对文件进行操作; l 使用文件关闭函数后再关闭文件。 1. 打开文件函数fopen 可使用fopen函数完成文件操作第一步,该函数定义为: FILE *fopen(const char * filename,const char * mode);

其中,参数filename是文件名字符串,mode为文件打开的模式。使用fopen函数时应注意: (1) 返回值是返回打开文件的指针,如果文件不存在或者不能找到文件,则fopen调用返回空指针(NULL),表示文件打开失败。

(2) 参数mode可取以下值: l “r”:以只读方式打开文件; l “w”:以写方式打开文件,如果文件已经存在,其内容将被破坏; l “r+”:用读和写的方式打开文件(文件必须已经存在,否则将导致异常); l “w+”:用读和写的方式打开一空文件,如果该文件已经存在,其内容将被破坏; l “a+”:为了读文件和附加新内容而打开文件; l “t”:以以文本方式打开文件; l “b”:以二进制方式打开文件。

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); 使用fread和fwrite函数时应注意以下几点: (1) fread函数读文件后返回文件数据记录的数目。 (2) fwrite函数写文件后返回实际写入文件数据记录的数目。

(3) 参数buffer指向数据缓冲区。fread函数将读出的数据放在缓冲区中供程序使用;fwrite函数将待写入文件的数据放在缓冲区中以便写入文件。 (4) size为从文件中读出和写入文件的字节数。 (5) count为一次从文件读出数据的最大记录数和一次写入文件的最大记录数。 (6) stream为文件结构指针,在fread函数中为打开文件的指针;在fwrite函数中为把数据要写入文件的指针。

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

例8.3 建立一个名为FREAD.OUT的文件并写入25个字符,然后从该文件中读出这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("Write %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");

运行结果为: Write 25 items Number of items read = 25 Contents of buffer = zyxwvutsrqponmlkjihgfedcb

8.3.2 文件输入/输出流 在C++中,对文件的输入/输出操作提供了另一种操作方式,即流类库的文件操作,这些类是ofstream与ifstream文件输入/输出流类。对文件的操作也需要8.3.1节讲述的三个步骤。 1. 文件的输出 文件的输出由ofstream完成。ofstream由ostream类继承而来,并继承了它的操作,因此可以利用ofstream重载的操作符<<把数据写入文件流中。进行文件输出时首先要创建文件输出流ofstream类的一个对象。ofstream类的构造函数用于在不同情况下构造文件流。

ofstream类构造函数的定义如下: ofstream(); ofstream(const char * filename,int mode=ios::out,int prot=filebuf::openprot); 1) 文件的打开 第一个构造函数用于构造一个不带参数的流,如果需要可以再用它的open函数打开一个文件。open函数的定义如下: void open(const char * filename,int filemode = ios::out,int access = filebuf:: openprot);

open函数需要三个参数:第一个参数为字符串,即打开文件的文件名;第二个参数为文件模式,缺省为ios::out,表示按输出方式打开,其它文件操作模式见表8.3;第三个参数为文件的保护方式,有8种取值,其中,0表示普通文件,1表示只读文件,2表示隐含文件,4表示系统文件,以及它们的组合。例如,打开一个test1.dat文件可用如下语句: ofstream afile(); afile.open("test1.d 或 afile.open("test1.dat",ios::out|ios::binary);

表8.5 文件操作方式 操作模式 说 明 ios::in 使文件只用于数据输入 ios::out 使文件只用于数据输出 ios::app 表8.5 文件操作方式 操作模式 说 明 ios::in 使文件只用于数据输入 ios::out 使文件只用于数据输出 ios::app 使文件指针移至文件尾,并只允许向文件尾输出数据 ios::nocreate 若打开的文件不存在则返回打开失败信息 ios::noreplace 若打开的文件存在则返回打开失败信息 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);

2) 文件的数据写入函数 ofstream类是从ostream类继承而来的,因而可以使用ostream类的写数据函数和操作符把数据写入文件。写数据函数的原型如下: //写入字符 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 * ,int);  //移动输出文件的位置指针 ostream& seekp(streampos); ostream& seekp(streamoff,ios::seek_dir);  //取当前输出文件位置指针的值 streampos tellp();

3) 文件的关闭函数 ofstream类也是从fstreambase类继承的,因而可以使用fstreambase类的close();来关闭文件。 2. 文件的输入 文件的输入由类ifstream完成,它由iostream和fstreambase类继承而来,并继承了fatreambase类的操作符>>函数以及文件打开、从文件中读数据和关闭文件的函数。ifstream也提供了两构造函数: 第一个为: ifstream();

第二个为: ifstream(const char * filename,int mode = ios::in,int prot = filebuf::openprot); 1) 文件的打开 第一个构造函数用于构造一个不带参数的流,如果需要可以在用它的open函数打开一个文件。open函数的定义如下: void open(const char * filename,int filemode=ios::in,int access=filebuf::openprot); 第一个构造函数使用与第二个构造函数相同的文件名打开输入文件。

2) 文件的数据读出函数 可以使用istream类的读数据的函数和操作符从文件中读取数据,下面是读数据函数的原型。 //将文件数据读取到字符串内 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 , char ='\n'); int gcount() const{return x_gcount;} 3) 文件的关闭函数 ifstream类也是从fstreambase类继承的,可以使用fstreanmbase类的close();来关闭文件。

3. 字符文件操作举例 例8.4 将100以内的所有奇数存入字符文件"a:wr1.dat"中。 #include<iostream.h> #include<fstream.h> void main(void) { ofstream f1("a:wr1.dat"); //定义输出文件流,并打开相应文件 for(int i=1;i<100;i+=2) f1<<i<<" "; //向f1文件流输出i值 f1.close(); //关闭f1所对应的文件 }

例8.5 从字符文件"a:wr1.dat"中依次读出每个整数并按6个一行显示出来。 #include<iomanip.h> #include<fstream.h> void main(void) { ifstream f1("a:wr1.dat", ios::in | ios::nocreate); int x,i=1;

while(f1>>x) if(i++%6) cout<<x<<' '; else cout<<x<<endl; cout<<endl; f1.close(); }

运行结果为: 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99

例8.6 使用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); if(!fin) { cerr<<"Can't 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);

8.4 重载插入运算符和提取运算符 使用传统的C语言中的printf和scanf等输入函数编写的程序,当输入输出的数据类型发生变化时,必须重写所有的输入输出代码。使用C++流类后,这个问题不复存在,C++可以利用流类对象cin和cout的成员函数重载任意类的输入/输出操作。

流的输入运算符“>>”又称提取运算符,流的输出运算符“<<”又称插入运算符,它们都可以重载。 下面是一个用户定义的日期类Date。为保持和简单类型的输入/输出同样的形式,需要重载操作符<<和>>。重载的操作符<<用于输出Date类的成员变量,重载的操作符>>用于输入Date类的成员变量。由于重载的函数需要访问Date类的私有成员和保护成员,因此应该把这些重载的函数定义为Date类的友元。

例8.7 在用户定义的Date数据类中对流类运算符<<和>>进行重载。 #include<iostream.h> class Date { int mo,da,int y; 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;

从这个例子可以看出,只要定义好了某个类的输入/输出操作符重载,就能很容易地进行此类输入和输出操作,这正是C++的一个重要的优点。重载的操作符函数有以下几个特点应该注意: (1) 重载的操作符函数有两个参数,第1个参数是出现在<<或>>左边的操作数,第2个参数是出现在<<或>>右边的操作数,如果重载的是输出操作符<<,第1个参数是对流ostream类的引用;如果重载的是输入操作符>>,第1个参数是对流istream类的引用,第2个参数是对要定义的输入/输出类的引用,当然,也可以是该类的指针。

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

8.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("crest.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"; Point Point2(x,y); writefile<<Point1; writefile<<Point2; writefile.close(); ifstream readfile("ctest.sav"); if(!readfile)

{ cout<<"Can not open file"; exit(-1); } readfile>>Point1>>Point2; cout<<Point1<<endl; cout<<Point2<<endl; return 0;

小 结 C++的I/O流完全不同于C的I/O系统,它操作更简捷,更容易理解,它使标准I/O流、文件流和串流的操作在概念上统一了起来。有了控制符,C++更具灵活性,由它所重载的插入运算符,完全融入了C++的类及其继承的体系。