第十九章IO流

上传人:pu****.1 文档编号:567947134 上传时间:2024-07-22 格式:PPT 页数:144 大小:558KB
返回 下载 相关 举报
第十九章IO流_第1页
第1页 / 共144页
第十九章IO流_第2页
第2页 / 共144页
第十九章IO流_第3页
第3页 / 共144页
第十九章IO流_第4页
第4页 / 共144页
第十九章IO流_第5页
第5页 / 共144页
点击查看更多>>
资源描述

《第十九章IO流》由会员分享,可在线阅读,更多相关《第十九章IO流(144页珍藏版)》请在金锄头文库上搜索。

1、第十九章 I/O流本章主要内容I/O流的概念I/O标准流库文件流类串流类控制符使用I/O成员函数重载插入运算符插入运算符与虚函数文件操作有关输入、输出操作并没有在C+语言中定义,但它包含在C+的实现中,并作为C+的一个标准库 iostream类库提供。为什么要有C+流类库非类型安全问题#includeintj=10;floatf=6.98;main()printf(%d,f);scanf(%d,&f);scanf(%d,j);printf(%d,abcde);为什么要有C+流类库C语言的输入输出系统不支持用户自定义的对象或数据类型,如一定义:struct sample int i ; floa

2、t f; char *ch;s1;不能用输出函数来输出以上结构变量:printf(“%sample”,s1);C+中,用户自定义的对象很多。C+的类机制允许它可以建立一个可控制的输入输出系统。可以通过重载“”运算符来解决以上的问题。流类库和流流C+的的I/O是以字节流的形式实现的,流实是以字节流的形式实现的,流实际上就是一个字节序列。际上就是一个字节序列。每个流都和一种与设备相联系。与输入设备(如键盘)联系的流为输入流;与输入设备(如键盘)联系的流为输入流;与输出设备(如屏幕)联系的流为输出流。与输出设备(如屏幕)联系的流为输出流。流类库和流流类库和流lC+的iostream类库是提供一组类类

3、库是提供一组类,程序利用程序利用它们可以方便的与外部世界交换数据它们可以方便的与外部世界交换数据.C+的iostream类库是用继承的方法建立起来的一个输入输出类库。liostream类库有两个基类,即类库有两个基类,即streambuf类类和和ios类。类。lstreambuf类类提供对缓冲区的低级操作,如缓提供对缓冲区的低级操作,如缓冲区的设置、缓冲区的读写等。冲区的设置、缓冲区的读写等。lios类用来完成检查错误的格式化输入、输出。类用来完成检查错误的格式化输入、输出。本章主要内容本章主要内容lI/O流的概念流的概念lI/O标准流库标准流库l文件流类文件流类l串流类串流类l控制符控制符l

4、使用使用I/O成员函数成员函数l重载插入运算符重载插入运算符l插入运算符与虚函数插入运算符与虚函数l文件操作文件操作iosistreamistrstreamistream_withassignifstreamostreamostrstreamostream_withassignofstreamiostreamfstreamstrstreamstdiostreamI/O流类层次class ios;class istream: virtual public ios;class ostream: virtual public ios;class iostream: public istream,pu

5、blic ostream;C+中定义了四个标准流对象cin 一个istream类的对象,用于处理标准输入 cout 一个ostream类的对象,用于处理标准输出cerr 一个ostream类的对象,用于处理标准错误输出,没有缓冲,发给它的内容立即输出。clog 类似于cerr,但有缓冲,缓冲区满时被输出.在类ostream中,对“”运算符进行了重载:ostream& operator(const char *);ostream& operator(char);ostream& operator(short);ostream& operator(int);ostream& operator(lo

6、ng);ostream& operator(float);ostream& operator(double);在缺省情况下,标准输出设备是显示终端,标准输入设备是键盘。在任何情况下,标准错误输出设备总是显示终端。标准输出设备可以不是显示终端;但错误信息总是在显示屏幕上显示。#include void fn(int a,int b) if(b = 0) cerr “zero encountered.” else cout a/b endl;void main() fn(20,2); fn(20,0);本章主要内容本章主要内容lI/O流的概念流的概念lI/O标准流库标准流库l文件流类文件流类l串流

7、类串流类l控制符控制符l使用使用I/O成员函数成员函数l重载插入运算符重载插入运算符l插入运算符与虚函数插入运算符与虚函数l文件操作文件操作文件C+把文件看成是由数据序列组成的。根据数据的组织形式,文件可以分为文本文件和二进制文件。文本文件也称ASCII文件,每个字节存放一个ASCII字符。二进制文件是将数据按在内存中的存储形式存放到磁盘上。一般二进制文件占用的空间比较少。 如:整数100000只要4个字节。C+把把文文件件看看作作字字符符序序列列,即即文文件件是是由由一一个个字字符符数数据据顺顺序序组组成成的的。根根据据数数据据的的组组织织形形式式,文文件件可可分分为为文文本本文文件件和和二

8、二进进制制文文件件。文文本本文文件件又又称称ASCII文文件件,它它的的每每个个字字节节存存放放一一个个ASCII代代码码,代代表表一一个个字字符符。二二进进制制文文件件则则是是把把内内存存中中的的数数据据,按按其其在在内内存存中中的的存存储储形形式式原原样样写写到到磁磁盘盘上上存存放放。文文件件是是一一个个字字符符流流或或二二进进制制流流,它它把把数数据据看看作作是是一一连连串串的的字字符符,而而不不考考虑虑记记录录的的界界限限,它它对对文文件件的的存存取取以以字字符符为为单单位位进进行行。我我们们把把这这种种文文件件称称为为流流式式文文件件。在在C+中中,要要进进行行文文件件的的输输入入输

9、输出出,必必须须首首先先创创建建一一个个流流,然然后后将将这这个个流流与与文文件件相相关关联联,即即打打开开文文件件,此此时时才才能能进进行行读读写写操操作作,完完成成后后再再关关闭闭这这个个文文件件。这这是是C+中中进行文件输入输出的基本过程进行文件输入输出的基本过程。ofstream,ifstream,fstream是文件流类,在fstream.h中定义。其中,ftream是ofstream和ifstream多重继承的子类。文件流类不是标准设备,所以没有cout那样预先定义的全局对象。文件流类定义的操作应用于外部设备,最典型的设备是磁盘中的文件。要定义一个文件流类对象,须规定文件名和打开方

10、式。 类ofstream用于执行文件输出,该类有几个构造函数,其中最有用的是:ofstream:ofstream(char* pFileName, int mode=ios:out, int prot=filebuf:openprot); 第一个参数是指向要打开的文件名字串,第二和第三个参数说明文件如何被打开。 mode文件打开方式:文件打开方式: ios:ate:到输入或输出文件的文件尾 ios:in: 打开输入文件(ifstream 默认) ios:out: 打开输出文件(ofstream 默认) ios:nocreate :如果文件不存在,返回错误ios:noreplace : 如果文件

11、已存在,返回错误 ios:trunc : 如文件存在,清除文件内容(默认) ios:binary : 以二进制模式打开文件 ios:app :打开一个文件使新的内容始终添加在文件的末尾prot是文件保护方式 C+中中与文件处理相关的三个类:类 ifstream 执行文件的输入操作类 ofstream 执行文件的输出操作类 fstream 执行文件的输入/输出操作在C+中,要进行文件的输入输出操作,应该:先创建一个流对象先创建一个流对象 ofstream( const char* szName, int nMode = ios:out, int nProt = filebuf:openprot

12、);进行文件的读写操作进行文件的读写操作关闭文件关闭文件下面的程序在文件myname中,写入一些信息: #includevoid fn() ofstream myf(c:bctempmyname); /ios:out|ios:trunc方式 myf In each of the following questions, a related pairnof words or phrases is followed by five lettered pairsnof words or phrases.n;void main() fn();此处的文件名要说明其路径,斜杠要双写,因为编译器理解下的斜杠

13、是字符转换符。这 与包含头文件时的路径不一样,因为包含头文件是由编译预处理器处理的。 文件打开时,匹配了构造函数ofsteam:ofstream(char*),只需一个文件名,其他为默认,打开方式默认为ios:out|ios:trunc,即该文件用于接受程序的输出,如果该文件原先已存在,则其内容必须先清除,否则就新建。若要打开二进制文件,写方式,输出到文件尾,则: ofstream bfile(binfile,ios:binary|ios:ate); 又例如,要检查文件打开否,则用判断fail()成员函数: #include void fn() ofstream myf(myname); if

14、(myf.fail() /fail()=1表示失败 cerrerror opening file my namen; return; myf.; 例如,打开一个输入文件(要从文件中读数据): #include void fn() ifstream myinf(“abc.dat”,ios:nocreate); /若文件丢失,就报错 可以通过检查myinf.fail()来确定打开文件是否有错。 例如,打开同时用于输入和输出的文件: fstream myinout(abc.dat,ios:in|ios:out); 用ifstream打开的文件,默认打开方式为ios:in用fstream打开的文件,打

15、开方式不能默认。#include int main() ofstream fout(c:data.dat); if(! fout) cerrCant open file n; return 1; fout10 123.456a /从输入设备中输入一个字符从输入设备中输入一个字符 coutaendl; /输出一个字符输出一个字符 输出结果为:输出结果为:I 类类ostrstream用于执行串流输出,该类也有几个构造函数,用于执行串流输出,该类也有几个构造函数,其中最有用的是:其中最有用的是: ostrstream:ostrstream(char*,int size,int=ios:out);第一

16、个参数指出字符串数组,第二个参数说明数组大小,第一个参数指出字符串数组,第二个参数说明数组大小,第三个参数指出打开方式。第三个参数指出打开方式。 下面代码使用串流输入对字符串中的数据进行解读 #include#includechar* parseString(char* pString) istrstream inp(pString,0); /ios:in方式,读到Null结束 int aNumber; float balance; inp aNumber balance; /从串流中读入一个整数和浮点数 char* pBuffer =new char128; ostrstream outp(

17、pBuffer,128);/ios:out方式,字串长度128 outp a Number = aNumber /写入pBuffer中 , balance = balanceends;/使用ostrstream输出到流对象的时候,要用ends结束字符串 /如果不这么做就有溢出的危险 return pBuffer;void main() char* str =1234 100.35; char* pBuf =parseString(str); cout pBuf endl; deletepBuf; 运行结果为: a Number=1234,balance=10035 在函数parseString

18、()中,以pString为输入设备,先定义一个输人串流对象inp,从中输入一个整数和一个浮点数。然后,开辟一个字符串空间(pBuffer指向的128个字符)作为输出设备而定义输出串流对象outp,将从输入设备中输入的该两个变量值输出。本章主要内容本章主要内容lI/O流的概念流的概念lI/O标准流库标准流库l文件流类文件流类l串流类串流类l控制符控制符l使用使用I/O成员函数成员函数l重载插入运算符重载插入运算符l插入运算符与虚函数插入运算符与虚函数l文件操作文件操作C+中提供了两种进行格式控制的方法: 用ios类成员函数进行格式化 用控制符进行格式化控制用ios类成员函数进行格式化设置域宽函数

19、 width(int wid)设置精度函数 precision(int p) 设置填充字符函数 fill(char c)用控制符进行格式化控制控制符是以一个流引用作为参数,并返回同一流的引用,因此它可以直接嵌入到插入流中。C+中提供了一些标准控制符和标准控制符函数。1.用流对象的成员函数用流对象的成员函数 下面的程序改变输出精度: #includevoid fn(float interest, float amount) cout RMB amount = ; cout.precision(2); /置有效位数为2位 cout amount; cout nthe interest = ; co

20、ut.precision(4); /置有效位数为4位 cout interest endl;void main() float f1 =29.41560067; float f2 =12.567188; fn(f1,f2);运行结果为: RMB amount=13 the interest=29.42 precision()为cout对象的成员函数,在要求输出一定精度的数据之前,先调用这个精度设置成员函数。2用控制符用控制符 manipulators(控制符)是在头文件iomanip.h中定义的对象,与成员函数调用效果一样。控制符的优点是程序可以直接将它们插入流中,不必单独调用。 例如,用控制

21、符设置小数精度:#include #include void fn(float interest, float amount)cout RMB amount = setprecision(2) amount;cout nthe interest = setprecision(4) interest endl;void main() float f1 =29.41560067; float f2 =12.567188; fn(f1,f2);常用控制符和流格式控制成员函数控制符和流成员函数相对应,它们用法不同,但作用相同。 其中setw(n)或width(n)很特别,他们在下一个域输出后,又回到原

22、先的默认值。例如,输出下面的两个数: #include #include void main() cout.width(8); cout 10 20 endl;运行结果为: 1020运行结果中的下横线表示空格。整数20并没有按宽度8输出。setw()的默认值为宽度0,即setw(0),意思是,按输出对象的表示宽度输出。所以20就紧挨10了。若要每个数值都有域宽度8,则每个值都要设置: coutsetw(8) 10 setw(8) 20 endl; 从中得出,用控制符的方法更加直接。下面的程序打印一个倒三角形: #include #include void main() for(int n=1;

23、 n8; n+) cout setfill( ) setw(n) setfill(m) setw(15-2*n) mendl; 运行结果为: mmmmmmmmmmmmm mmmmmmmmmmm mmmmmmmmm mmmmmmm mmmmm mmm mcoutsetfill()setw(n)中所要显示的长度为n,但它本身长度只有1,所以 其余的内容就由setfill()来填充了,效果就使得,m前的空格逐行增加。同样,coutserfill(m)setw(15-2*n)中所要显示的长度为15-2*n,但它本身长度只有1,而且所要显示的是一个空格,setfill(m)的作用就是将15-2*n个空格

24、用其m来填充,由于15-2*n逐行递减,结果就显出一个用m构筑的倒三角形。 比较下列同样完成倒三角形显示的程序: #include void main() for(int n =1; n =7; n+) for(int j =1; j =n; j+) cout ; for(int k =1; k =15-2*n; k+) cout m; cout endl; 但流成员函数也有其优点,它种类多,而且可以返回以前的设置,便于恢复设置。例如,下面的函数设置某精度输出,然后恢复成原来的精度设置: #include void main() float value =2.345678;cout value

25、; int prePrecision; prePrecision =cout.precision(4); cout value; cout.precision(prePrecision); cout value; 运行结果为: 2.345682.3462.23568假定程序中原来的精度设置不知道,“cout.precision(4)”可以返回原来设置的精度,保存该值在prePrecision变量中,使得最后用该值恢复原来的设置:示例:示例:ASCII码表码表#include#includeintmain()inti,j=0;for(i=32;i127;i+)coutsetw(4)hexiHse

26、tw(2)char(i);j+;if(j%8=0)coutendl;return0;程序运行结果:20H 21H ! 22H 23H # 24H $ 25H % 26H & 27H 28H ( 29H ) 2aH * 2bH + 2cH , 2dH - 2eH . 2fH /30H 0 31H 1 32H 2 33H 3 34H 4 35H 5 36H 6 37H 738H 8 39H 9 3aH : 3bH ; 3cH 3fH ?40H 41H A 42H B 43H C 44H D 45H E 46H F 47H G48H H 49H I 4aH J 4bH K 4cH L 4dH M 4

27、eH N 4fH O50H P 51H Q 52H R 53H S 54H T 55H U 56H V 57H W58H X 59H Y 5aH Z 5bH 5cH 5dH 5eH 5fH _60H 61H a 62H b 63H c 64H d 65H e 66H f 67H g68H h 69H i 6aH j 6bH k 6cH l 6dH m 6eH n 6fH o70H p 71H q 72H r 73H s 74H t 75H u 76H v 77H w78H x 79H y 7aH z 7bH 7cH | 7dH 7eH 本章主要内容本章主要内容lI/O流的概念流的概念lI/O标

28、准流库标准流库l文件流类文件流类l串流类串流类l控制符控制符l使用使用I/O成员函数成员函数l重载插入运算符重载插入运算符l插入运算符与虚函数插入运算符与虚函数l文件操作文件操作输出字符的成员函数ostream& put(char )ostream& write(const char * str,int length);put( )函数读写二进制文件函数读写二进制文件put( )是是输输出出流流类类ostream中中的的成成员员函函数数,它它可可以以向向与与流流对对象象连连接接的的文文件件中中写写入数据,每次写入一个字节(字符)。入数据,每次写入一个字节(字符)。put( )函数的原型如下:函

29、数的原型如下: ostream &put(char ch); put( )函数将字符函数将字符ch写入流中。写入流中。put函数把一个字符写到输出流中,函数把一个字符写到输出流中,下下面面两两个个语语句句缺缺省省是是相相同同的的,但但第第二二个个受受该该流流的的格格式式化化参参量量的的影影响响:cout.put(A); /精确地输出一个字符精确地输出一个字符coutA;/输出一个字符输出一个字符,但此前设置的宽度和填充方式在此起作用但此前设置的宽度和填充方式在此起作用 void main()char letter;for(letter=97;letter97+26;letter+)cout.p

30、ut(letter);将将a至至z写入文件然后读出并显示写入文件然后读出并显示#include#includevoidtest_write()ofstreamfs(“d:/test.dat”);inti;charc=a;for(i=0;i26;i+)fs.put(c+);voidtest_read()ifstreamfs(“d:/test.dat”);charc;while(fs.get(c)coutc;voidmain()test_write();test_read();write( )函数函数write( )是流类是流类ostream的成员函数,利用该的成员函数,利用该函数,可以把函数,可

31、以把buf所指的缓冲区所指的缓冲区num个字节个字节写到相应的流上。写到相应的流上。函数原型:函数原型: ostream &write(const unsigned char *buf, int num);注意:如果在注意:如果在num个字节被读出之前就达到个字节被读出之前就达到了文件尾,则了文件尾,则read( )只是停止执行,此时缓只是停止执行,此时缓冲区包含这些字符。我们可以用另一个成员冲区包含这些字符。我们可以用另一个成员函数函数gcount( )统计出有多少字符被读出。统计出有多少字符被读出。gcount( )的原型如下:的原型如下: int gcount( );它返回;它返回所读取

32、的字节数。所读取的字节数。用用write( )函数向文件函数向文件test中写入双精度数与字符串。中写入双精度数与字符串。# include # include # include # include # include # include void main( )void main( ) ofstreamofstream out(out(”testtest”);); if (! out)if (! out) coutcout“cannot open output file .ncannot open output file .n”; ; return; return; double num=

33、100.45; double num=100.45; char char strstr = =”This is a testThis is a test”; ; out.writeout.write (char * )& (char * )&num,sizeofnum,sizeof (double ); (double ); out.writeout.write ( (strstr, , strlenstrlen ( (strstr);); out.closeout.close ( ); ( ); 程序执行后,屏幕上不显示任何信息,但程序已将双精度程序执行后,屏幕上不显示任何信息,但程序已将双

34、精度100.45100.45和字符串和字符串“this is a testthis is a test” 以二进制形式写入文件以二进制形式写入文件testtest中。中。若用若用“写字板写字板”打开是看不出内容的打开是看不出内容的read( )read( )函数函数, ,可以读取文件可以读取文件testtest中的数据,并在屏幕上显示出来中的数据,并在屏幕上显示出来write函数把一个内存中的一块内容写到一个输出文件流中,长度参数指出写的字节数。下面的例子建立一个输出文件流并将Date结构的二进制值写入文件:例 向文件输出i ncludestruct Dateint mo,da,yr;void

35、 main()Date dt=6,10,92; ofstream tfile(date.dat,ios:binary);/二进制值写入文件 tfile.write(char*)&dt,sizeof dt);write函数当遇到空字符时并不停止,因此能够写入完整的类结构,该函数带两个参量,一个char指针(指向内存数据的起始地址)和一个所写的字节数。注意在该结构对象的地址之前需要char*做强制类型转换。可以ifs.read(char *)&a,sizeof(Date); 读出输入流的getline函数允许从输入流中读取多个字符,可以指定输入终止字符,读取完成后,从读取的内容中删除该终止字符.输

36、入流的read函数从一个文件读字节到指定的存储器区域,所读字节数由长度参数确定.若没给长度参数,当遇到文件结束时读结束.1用用getline()读取输入行读取输入行 当程序使用cin输入时,cin用空白符和行结束符将各个值分开。根据所需输入的值, 可能需要读取一整行文本并且分开不同的域。为了读取一行文本,可以使用getline成员函 数。其函数原型为: getline(char* line,int size,char=n); 第一个参数是字符数组,用于放置读取的文本,第二个参数是本次读取的最大字符个 数,第三个参数是分隔字符,作为读取一行结束的标志。例如,下面的函数从键盘读取一行文本:#inc

37、ludevoid fn() char str128; cout Type in a line Of text andpress Enter endl; cin.getline(str,sizeof(str); cout You typed: str endl; 在默认状态,getline成员函数读字符直到回车,或者读到指定的字符数。为了要在遇到某个字符(比如字母X)时,结束输入操作,可以按下面方式使用: cingetline(1ine,sizeof(1ine),X);下面程序在遇到X字符处结束第一个输入操作,然后执行第二个输入: #include void main() char str128

38、; cout Type in a line of text and press Enter endl; cin.getline(str, sizeof(str), X); cout First line: str endl; cin.getline(str, sizeof(str); cout Second line: “cin.getline();”与与“cinstr;”的一个的一个不同是,前者输入一行,行中可以包含空格,不同是,前者输入一行,行中可以包含空格,后者却以空格或回车作为字串结束,不包含空后者却以空格或回车作为字串结束,不包含空格。格。例: 统计文件abc.dat中行数。void

39、 main() ifstream fin(c:abc.dat);int count=0;char buffer100;while(!fin.eof()/或while(!fin)fin.getline(buffer,sizeof(buffer);count+=1; coutcount;2用用read()读字节read成员函数从一个文件读字节到一个指定的存储器区域,由长度参数确定要读的字节数。如果给出长度参数,当遇到文件结束或者在文本模式文件中遇到文件结束标记字符时读结束。函数原型:函数原型:istream&read(unsignedchar*buf,intnum);read()是是类类istre

40、am中中的的成成员员函函数数,其其功功能能为为:从从相相应应的的流流中中读读取取num个个字字节节(字字符符),并并把把它它们们放放入入指指针针buf所指的缓冲区中。所指的缓冲区中。调用格式:调用格式:read(缓冲区首址,读入的字节数缓冲区首址,读入的字节数);注注意意:“缓缓冲冲区区首首址址”的的数数据据类类型型为为unsignedchar*,当输入其它类型数据时,必须进行类型转换,当输入其它类型数据时,必须进行类型转换,例例如如:intarray=50,60,70;定定义义了了一一个个整整型型数数组组array,read(unsignedchar*)&array,sizeof(array

41、);对对整整型型数数组组array,为为了了把把数数据据从从文文件件读读入入到到它它中中,必必须须在在read()函函数数中中把把它它转转换换为为unsignedchar*类类型型。由由sizeof()函数确定要读入的字节数。函数确定要读入的字节数。向文件向文件test中写入双精度数与字符串并读出中写入双精度数与字符串并读出用用write( )函数写入函数写入# include # include # include void main( ) ofstream out(”test”); if (! out) cout“cannot open output file .n”; return; d

42、ouble num=100.45; char str =”This is a test”; out.write (char * )&num,sizeof (double ); out.write (str, strlen (str); out.close ( ); 用用read( ) 函数读取函数读取#include#include#includevoidmain()()ifstreamin(”test”);if(!in)cout”cannotopeninputfile.n”;return;doublenum;charstr80; :memset(str,0,80);in.read(char*

43、)&num,sizeof(double);in.read(str,14);coutnumstr;in.close();程序运行结果为:程序运行结果为:100.45Thisisatestwrite( )写一个二进制记录到文件写一个二进制记录到文件将Date结构的二进制值写入文件date.dat :例 向文件输出i ncludestruct Dateint mo,da,yr;void main()Date dt=6,10,92; ofstream tfile(date.dat,ios:binary);/二进制值写入文件 tfile.write(char*)&dt,sizeof dt);Read()

44、从一个从一个date.dat文件读一个二进制记录到一个结构中文件读一个二进制记录到一个结构中#include#includevoid main( ) struct Date int mo,da,yr; date; ifstream is (date.dat,ios:binary |ios:nocreate); if(is) is.read(char*)& date,sizeof(date); coutdate.mo date.da date.yrendl; else coutERROR:Cannot open file payroll.endl; 练习:图片复制const int bufSiz

45、e = 12; coutplease input a file pathname:; ifstream from(c:/d.jpg, ios:binary); if(!from) coutcannot open the file:endl; coutplease input a file new pathname:; ofstream to(c:/d2.jpg, ios:binary); if(!to) cout”相像.但get函数在读入数据时包括空白字符,而“”在缺省时拒绝接受.形式:intint get(); get();istreamistream& & get(charget(char

46、 &); &);istreamistream& & get(charget(char*,*,int,charint,char _ _delimdelim= =nn) )#include #include void main() char letter; while(!cin.eof() letter =cin.get(); letter =toupper(letter); if(letter=Y) cout Y be met.; break; cout letter; 或char letter; while(letter =cin.get() letter =toupper(letter);

47、if(letter=Y) cout Y be met.; break; cout ch19_11ch19_11.cpp#INCLUDEIOSTREAM.H#INCLUDE“letter=cin.get();”与“cinletter;”都是从输入流中取一个字符,但却有区别。默认情况下,cin1etter将跳过任何在文件中发现的任何空白字符(空白字符指空格、tab符、backspace符和回车符)。而cin.get()则不跳过空白字符。3用用get()输入一系列字符输入一系列字符 用get()成员函数的第二种形式可以输入一系列字符,直到输入流中出现结束符或所读 字符个数已达到要求读的字符个数。其原

48、型为:istream& istream:get(char*,int n,char delim=n);由于可以规定输入字符个数,所以下面不安全的代码: ifstream fin(abc.dat); char buffer80; finbuffer; /不能保证输入字符个数在80以内 可以改写为: ifstream fin(abc.dat); char buffer80; fin.get(buffer,80); /保证输入字符个数在80以内 -geline()和和get()第二种形式相同。唯一的例外是第二种形式相同。唯一的例外是getine()从输入流中输入一系列字从输入流中输入一系列字 符时包括

49、分隔符,而符时包括分隔符,而get()不不包括分隔符。包括分隔符。4输出一个字符输出一个字符下例程序使用put()成员函数,在屏幕上依次显示字母表中的字母: #include void main() char letter; for(letter =A; lettercoutletter;与cout.put(letter);有一个区别,前者显示以该数据类型表示的形式,后者将参数值以字符方式显示。所以,若letter是char型,那么这两种方法都可以用来显示字母,若letter为int型,那么前者将在屏幕上显示65到90的数字,而不是字母A到Z。上述流成员函数同样适用于文件流和串流。例如,下面的

50、程序打开以命令行变元形式指定的文件,然后逐个读取字符并显示: #include #include void main(int argc, char* argv ) ifstream in(argv1); if(in.fail() cerr Error opening the file: argv1 endl; return; while(!in.eof() cout.put(char(in.get(); in.close();put()成员函数的参数,是文件流对象in的成员函数get()的返回值。#include void main()char letter;while(!cin.eof()l

51、etter=cin.get();letter=toupper(letter);if(letter=Y)cout y be metendl;break;coutletter;int main() char c;const int SIZE = 80;char buffer1SIZE,buffer2SIZE;coutbuffer1;coutn The string read with cin was:nbuffer1n; cin.get(buffer2,SIZE);coutThe string read with cin.get was:nbuffer2endl;return 0; #includ

52、e void main() ifstream fin(c:abc.dat); char buffer80; finbuffer; voidmain()ifstreamfin(c:abc.dat);charbuffer80;fin.get(buffer,80);输入流的getline函数允许从输入流中读取多个字符,可以指定输入终止字符,读取完成后,从读取的内容中删除该终止字符.输入流的read函数从一个文件读字节到指定的存储器区域,所读字节数由长度参数确定.若没给长度参数,当遇到文件结束时读结束.输出字符的成员函数ostream& put(char )ostream& write(const c

53、har * str,int length);voidmain()charletter;for(letter=97;letter97+26;letter+)cout.put(letter);本章主要内容本章主要内容lI/O流的概念流的概念lI/O标准流库标准流库l文件流类文件流类l串流类串流类l控制符控制符l使用使用I/O成员函数成员函数l重载插入运算符重载插入运算符l插入运算符与虚函数插入运算符与虚函数l文件操作文件操作C+重载左移运算符执行输出,对程序员来说,很满足。因为你可以随意重载同一个运算符去执行自己定义的类输出。左移运算符也称插入运算符,它比较形象,执行“coutx;”输出时,好象x

54、被插入到输出设备上。重载插入运算符的特性使得流I/O可扩展这与printf()是重要的区别。 要使得插入运算符“”能输出用户自定义类型,必须对其进行重载。定义输出运算符重载函数的一般格式如下:ostream& operator(ostream &stream, class_name obj) 函数体函数中第一个参数是对ostream对象的引用。例1:对插入运算符进行重载,打印人民币类对象。问题:插入运算符重载为成员函数,还是重问题:插入运算符重载为成员函数,还是重载为友元函数?载为友元函数?class RMBprotected:unsigned int yuan;unsigned int jf

55、;public:RMB(double v=0.0); RMB operator *(double d);friend ostream& operator(ostream& oo,RMB&d);RMB:RMB(double v)yuan=v;jf=(v-yuan)*100.0+0.5;RMB RMB:operator *(double d)double td=(yuan+jf/100.)*d;return RMB(td);ostream& operator(ostream& out,RMB& d)outd.yuan.setfill(0)setw(2)d.jfflush;return out;vo

56、id main()RMB rmb(1.5);coutrmb=rmbendl;rmb=rmb*2.0;coutrmb=rmb重载插入运算符中最后一条语句是重载插入运算符中最后一条语句是retum oo;”,为什么要返回传递给,为什么要返回传递给它的它的ostream对象对象? 这样做允许该运算符在单个表达式中与其它插入运算符连结在一起。这样做允许该运算符在单个表达式中与其它插入运算符连结在一起。的运算顺序是从左到右,下面的表达式的运算顺序是从左到右,下面的表达式 void fn(RMB r,float interest) cout Sum of these=r + interestendl; 被

57、翻译成:被翻译成: void fnRMB r,float interest (coutSum of these =)r)+)interest)endl; 第一次插入向第一次插入向cout输出字符串输出字符串“Sum of these=”。该表达式的结果是对。该表达式的结果是对象象coat,它然后被传递给重载插入运算符,它然后被传递给重载插入运算符 ostream& operator(ostream&,Peru&) 这个运算符返回它的这个运算符返回它的ostream对象,这一点很重要,这样做,对象才能对象,这一点很重要,这样做,对象才能被传递给下一个插入运算符。被传递给下一个插入运算符。 假设重

58、载插入运算符返回类型是void,像前面那样相当有效的用法将出现编译错。因 为你不能向void内插入一个字符串。下列错误更糟糕,因为更难发现: ostream& operator(ostream& os,RMB& rmb) rmb.display(os); return cout; 这个运算符没有返回它给出的ostream对象,而返回ostream对象cout。cout最常用,编译也正确,但是在下面程序中: void fn(iht acc,RMB& balance,char* pName) ofstream outfaccountsdat,ios:ate; outf acc balance pN

59、ame endl; int acc通过outf的插入运算符输出到outf中,返回outf。然后RMB通过重载插入运算符输出到outf中,可是错误地返回cout,而不是outf,现在pName输出到cout中,而不是输出到想要输出的文件中。例2:用输出/入复数#includeclass complex float real,image; public:complex(float r, float i) real=r; image=i;complex() real=0; image=0;friend complex operator+(complex,complex);friend ostream

60、 &operator(istream &,complex &);用输出/入复数/定义重载运算符+complex operator +(complex a,complex b)complex temp;temp.real=a.real+b.real;temp.image=a.image+b.image;return temp;用输出/入复数/定义重载运算符ostream &operator(ostream &output,complex &obj) output0) output“+”; if(obj.image !=0) outputobj.imagei; return output;用输出/

61、入复数/定义重载运算符istream &operator(istream &input,complex &obj) coutobj.real; inputobj.image; return input;用输出/入复数/主函数main()complex c1(2.4, 4.6), c2, c3;cout“The value of c1 is:”c1c2;cout “The value of c2 is:”c1endl;c3=c1+c2;cout “The value of c3 is:”c1endl;return 0;用输出/入复数/运行结果:The value of c1 is:2.4+4.6

62、iInput the real and image of a complex:3.7 2.5The value of c2 is:2.4+4.6iThe value of c3 is:2.4+4.6i本章主要内容本章主要内容lI/O流的概念流的概念lI/O标准流库标准流库l文件流类文件流类l串流类串流类l控制符控制符l使用使用I/O成员函数成员函数l重载插入运算符重载插入运算符l插入运算符与虚函数插入运算符与虚函数l文件操作文件操作插入运算符不能是成员函数,也就不能成为虚函数,因此对于上节中的重载插入运算符定义,在下例的派生类中,显得无能为力:class RMB friend ostream&

63、 operator(ostream& out,RMB&d); /;class Derived: public RMB public: Derived(double v,int n):RMB(v),c(n) private: int c;Main() Derived a(5.5,3); cout a; /a.c将不能显示 couta;能匹配重载的插入运算符,但是执行的结果是输出a的人民币值而不能输出a作为派生的附加信息a.c。 解决方法:在重载插入运算符中,不直接实现输出,而是调用出disPlay()成员,再将display()定义为虚函数。这样,重载插入运算符的行为便可随display()的不

64、同而不同。这就是上一节为什么要间接实现重载插入运算符的用意。class RMBprotected:unsigned int yuan;unsigned int jf;public:RMB(double v=0.0) RMB operator *(double d); virtual display(ostream& out) outyuan.setfill(0)setw(2)jfflush; ;ostream& operator(ostream& oo,RMB& d)d.display(oo);return oo;classDerived:publicRMBpublic:Derived(dou

65、blev,intn):RMB(v),c(n)display(ostream& out) outsetfill( )c; private:intc;main()Deriveda(5.5,3);couta;1先定义一个抽象类class Currencyprotected:unsigned yuan;unsigned jf;public:Currency(double v=0.0)yuan=v;jf=(v-yuan)*100.+0.5;virtual void display(ostream& out)=0;2派生人民币类等子类派生人民币类等子类 class RMB:public Currencyp

66、ublic:RMB(double v=0.0):Currency(v)virtual void display(ostream& out)outyuan.setfill(0)setw(2)jfsetfill(q)setw(4)RMB;class Dmark:public Currency /德国马克 Dmark(double v = 0.0) :Currency(v) virtual void di splay ( ostream& out) out yuan . setfill(0) setw(2) jf setfill( ); out DPf; ;3. 定义插入运算符定义插入运算符ostr

67、eam& operator(ostream& oo,Currency& d)d.display(oo);ooendl;return oo; 4. 应用应用void fn(Currency& c) cout Deposit is c endl;void main() RMBrmb(5.5); fn(rmb); Dmark mark(10.6); fn(mark);类Currency有两个子类RMB和Dmark。Currency中display()成员定义为纯虚函数。在每一个子类中,display()成员被重载,从而可以适当的格式输出相应对象。重载插入运算符函数对display()的调用是一个虚调

68、用。因此当它被传递以RMB类对象时,则像人民币那样输出;当它被传递以Dmark对象时,则像德国马克那样输出。因而,尽管重载的插入运算符不是虚拟的,因为它调用了一个虚函数,结果令人满意。 重载插入运算符的参数Currency&必须为引用,如果以值传递,那么对于: ostream& operator(ostream& oo, Currency& c)编译将报错。因为Currency是抽象类,不能构造该类的对象。本章主要内容本章主要内容lI/O流的概念流的概念lI/O标准流库标准流库l文件流类文件流类l串流类串流类l控制符控制符l使用使用I/O成员函数成员函数l重载插入运算符重载插入运算符l插入运算

69、符与虚函数插入运算符与虚函数l文件操作文件操作1文件输出文件输出 在文件输出时,往往涉及到大量相关记录的集合。把文件看作是相关记录的集合。如 要输出若干个学生对象,每个学生对象含有学生姓名、学号、成绩等,将其看作是一个数据记录。例如,下面的程序输出三个学生对象,其中一个大学生,两个硕士生 文件输出实例:输出三个学生对象的数据到一个文件(abc.dat)中,其中一个大学生,两个硕士生。student.cppmaster.cppmain.cppstudent.hmaster.h/* student.h *#include #include #ifndef STUDENT#define STUDEN

70、T/大学生类大学生类class Studentpublic: Student(char* pS, unsigned num, float g) strcpy(pName,pS); uID=num; grade=g; virtual void display(ostream& out);protected: char pName20; unsigned int uID; float grade;ostream& operator(ostream& out, Student& st);#endif/* student.cpp */*#include student.h#include #inclu

71、de void Student:display(ostream& out) out setiosflags(ios:left) setw(20)pName uID ,setiosflags(ios:right) setw(4) grade;/插入操作符ostream& operator(ostream& out, Student& st) st.display(out); out endl; return out;/* master.h */*#include student.h#include /硕士生类class MasterStudent: public Studentpublic: M

72、asterStudent(char* pS, unsigned num, float g, char t) :Student(pS,num,g),type(t) void display(ostream& out);protected: char type;/* master.cpp */*#include #include master.hvoid MasterStudent:display(ostream& out) Student:display(out); out , type;/* main.cpp */*#include #include student.h#include mas

73、ter.hvoid main() ofstream out( abc.dat ); Student s1(Dill Arnson, 12567, 3.5); MasterStudent s2(Welch Shammas, 12667, 4.1, A); MasterStudent s3(Portel Braumbel, 12579, 3.8, B); out s1; out s2; out s3;运行结果可以在打开的文件中看到: Dill Arnson 12567 3.5 Welch Shammas 12667 4.1 A Portel Braumbel 12579 3.8 B2. 文件输入如

74、果要打开一个文件用于输入,可以用ifstream类。用上例中的类定义,假定文件abc.txt中的内容为: Dill Arnson 12567 3.5 A Welch Shammas 12667 4.1 A Portel Braumbel 12579 3.8 B将该文件的内容逐条输入,创建MasterStudent对象,屏幕输出该记录。其程序为一个工程:#include #include student.h#include master.h#include void main() ifstream fin(e:bctempabc.txt); char sFirst10; char sLast10

75、; unsigned int uid; float nGrade; char type; char name20; Student * pS; int i=0; finsLast sFirst uid nGrade type; while(!fin.eof() strcpy(name,strcat(sLast, ); strcpy(name,strcat(name,sFirst); pS=new MasterStudent(name,uid,nGrade,type); cout student # +i : sLast sFirst uid nGrade type; 运行结果为: studen

76、t #1:Dill Arnson 12567 3.5 A student #2:Welch Shammas 12667 4.1 A student #3:Portel Braumbel 12579 3.8 B 程序中先将文件的一行分5个数据项读人(一条记录),然后将前两项组合成一个名字。用名字name,学号uid,成绩nGrade,类别type这四项初始化一个MasterStudent堆对象,在屏幕上输出。随后,继续这一过程,直到文件尾。文件尾的判断标志为fin.eof()成员函数。1表示文件尾,0表示未到文件尾。练习 改进当文件是相关记录的集合时,可通过重载插入运算符“”进行文件的输入、输出

77、操作。文件输出实例:输出三个学生对象的数据到一个文件(abc.dat)中,其中一个大学生,两个硕士生。Student.cppMaster.cppMain.cppStudent.hMaster.hclass Studentprotected:char pName20;unsigned int uID;double grade;public:Stu(char* pS,unsigned int num, double g) strcpy(pName,pS);uID=num;grade=g;virtual void display(ostream& out);/ Student.h#include S

78、tudent.h#include #include void Student:display(ostream& out)outsetiosflags(ios:left)setw(20)pName uID setiosflags(ios:right)setw(4)grade;ostream& operator (ostream& out,Student& st)st.display(out); outendl;return out;/ Student.cpp#include class Master:public Studentprotected:char type;public:Master(

79、char *pS=aa,unsigned num=0,double g=0.0,char t=C):Student(pS,num,g),type(t)void display(ostream& out);/ Master.h#include #include Student.h#include Muster.hvoid Master:display(ostream& out)Student:display(out);out type;/ Master.cpp#include #include Student.h#include Muster.hvoid main()ofstream out(“

80、c:abc.txt);Student s1(Dill Arnson,12567,3.5);Master s2(Welch Shammas,12556,3.1,A);Master s3(Portel Braumbel,12679,3.6,B);outs1s2s3;out.close();/ main.cpp文件输入实例:读入文件(abc.dat)中的内容,并显示在屏幕上。abc.dat:DillArnson125673.5WelchShammas125563.1APortelBraumbel126793.6Bclass Studentprotected:char pName20;unsigned

81、 int uID;double grade;public: Student( )Student(char* pS,unsigned int num, double g) virtual void display(ostream& out);virtual void input(istream& in);/ Student.h#include Student.h#include #include void Student:display(ostream& out)/ ostream& operator (istream& in, Student& st)st.input(in);return i

82、n;/ Student.cpp#include class Master:public Studentprotected:char type;public:Master(char *pS=aa,unsigned num=0,double g=0.0,char t=C):Student(pS,num,g),type(t)void display(ostream& out);virtual void input(istream& in);/ Master.h#include #include Student.h#include Muster.hvoid Master:display(ostream

83、& out) / void Master:Input(istream& in)Student:Input(in);intype;/ Master.cpp/ void main()Student s1;Master s2;ifstream in(c:abc.dat); while(!in.eof() ins1;couts1s2;couts2s2;couts2endl;in.close();/ main.cppoutput:DillArnson125673.5WelchShammas125563.1APortelBraumbel126793.6B使用存储对象的方法对象读入:对象读入:Student

84、 s1(Dill Arnson, 12567, 3.5);MasterStudent s2(Welch Shammas, 12667, 4.1, A);MasterStudent s3(Portel Braumbel, 12579, 3.8, B); ofstream tfile(date.dat,ios:binary);tfile.write(char*)&s1,sizeof s1); tfile.write(char*)&s2,sizeof s2); tfile.write(char*)&s3,sizeof s3); tfile.close();对象读出:Student* student=new Student; ifstream is (date.dat,ios:binary);if(is) is.read(char*)student,sizeof(Student); coutpName uID gradeendl; /读取第一条数据读取第一条数据 is.read(char*)student,sizeof(Student); coutpName uID gradeendl; /读取第二条数据读取第二条数据

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 医学/心理学 > 基础医学

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号