资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,面向对象程序设计 第二版,第十章,I/O,流,本章概要:,本章着重讲述,C+,流库、预定义类型数据的输入,/,输出、格式控制、自定义类型数据的输入,/,输出、文件的输入,/,输出等内容。,面向对象程序设计 第二版,本章快速索引,面向对象程序设计 第二版,10.1 C+,流库概述,10.2,预定义类型的输入,/,输出,10.3,格式控制,10.4,自定义类型的输入,/,输出,10.5,文件的输入,/,输出,10.6,小结,C+,为什麽要建立自己的输入输出系统?,1.C,虽然具有一个灵活和功能强大的输入输出系统,但它并不支持自定义类型。例如:,class account,char name30;,double balance;,public:,account();,account(char,*,double);,;,10.1 C+,流库概述,account,acnt,;,scanf(“%account,”,&,acnt,);/,错误,不支持,account,类型,account acnt1(John,3000.0);,printf(“%account,”,acnt1);/,错误,不支持,account,类型,输入函数,scanf,和输出函数,printf,的格式串形参只能与系统预定义类型匹配,不能通过重载定义,scanf,和,printf,函数,使它们的格式串形参能匹配任意用户自定义类型。,2.,面向对象程序设计必须定义众多的用户自定义类,如何以面向对象的设计原则和方法,为自定义类设计,既规格,统一,,又适应,个性,化的,输入输出操作,行为是十分必要的。,因此,C+,必须建立一个能通过对输入输出操作重载的方法实现对任意自定义类型对象输入输出支持的系统。,10.1 C+,流库概述,所谓“流”,就是,数据从源,(,数据的生产者,),到漏,(,数据的消费者,),的流动,。,输入,/,输出是一种基本的数据传递操作,它可以理解为字符序列在计算机内存与外设之间的流动;,C+,将数据从一个对象到另一个对象的流动抽象为,流,(stream),,将实现设备之间交换信息的类称为,流类,;,按面向对象方法组织的多个流类及其类层次集合构成了,I/O,流类库,简称为,流库,。,面向对象程序设计 第二版,10.1 C+,流库概述,图,10.1,strstreambuf,类及其派生类,streambuf,类主要负责缓冲区的处理。图,10.1,为它们之间的层次关系。,面向对象程序设计 第二版,流库中的每一个流类都定义了一种设备之间的信息交换方式,按信息流动方向的不同,可以分为输入,/,输出流。,与输入设备(如键盘)相联系的流称为输入流。,与输出设备(如屏幕)相联系的流称为输出流。,与输入输出设备相联系的流称为输入输出流。,面向对象程序设计 第二版,图,10.2,ios,类及其派生类,10.1 C+,流库概述,系统将自动打开几个预定义流,:,cin,,称为标准输入流,缺省时为键盘。如:,int,m,n,;,cin,mn;/100 22,输入时数据间加以空格,cout,,称为标准输出流,缺省时为显示器。如:,int,x=9;,cout,“x=“x”,重载为输入运算符;,ostream,流类相对于系,统预定义类型把运算符“,跳过空白符,然后读入与输入变量类型相对应的值。,int,n;,float x;,cin,nx;,面向对象程序设计 第二版,当输入字符串,(,即,类型为,char*,的变量,),时,运算符,“”,的作用是跳过空白,读 入以下的非空白字符,直到遇到另一个空白字符为止,并在串尾放一个字符“,0”,。,char*,mystr,;,mystr,=new char100;,cin,mystring,;,输入字符串:,Object_oriented,programming,输出:,Object_oriented,不同类型的变量一起输入时,系统除了检查是否含有空白符之外,还完成输入数据与变量类型的匹配。,int,n;,float x;,cin,nx;,输入:,35.78 89.25,输出:,n=35 x=0.78,输入运算符“,”,采用左结合方式工作,并返回它的左操作数,因此,可以把多个输入操作组合到一个语句中。,int,i,j,;,cin,i;,cin,j,;,cin,ij;,10.2.4,输出运算符,输出运算符“,”,也采用左结合方式工作,并且返,回它的左操作数,因此,可以把多个输出操作组合,到一个语句中,使用起来很方便。,int,n=89;,double d=3.1416;,cout,“n=”n“,d=”dn;,面向对象程序设计 第二版,使用输出运算符“,”,进行输出操作时,不同类型的数据也可以组合在一条语句中,例如上面的例子中就是把整型变量和双精度型变量的输出放在同一条语句中。,重载并不能改变运算符的优先级,因此,必须特别注意表达式的求值顺序。,cout,x&y,n;,cout,(,x&y,)1)/,使,i,中为,1,的位不断右移,if(i,&f),cout,1;/,若,f,中某位为,1,则输出,1,else,cout,0;,cout,n;,面向对象程序设计 第二版,10.3.1,用,ios,类成员函数控制格式,void main(),long f;,f=,cout.flags,();/,取当前状态标志,showflags(f,);,cout.setf(ios:showpos|ios:scientific,);/,追加标态字,f=,cout.flags,();,showflags(f,);,cout.unsetf(ios:scientific,);/,去掉,scientifin,标志,f=,cout.flags,();,showflags(f,);,面向对象程序设计 第二版,程序输出如下:,0010000000000001,0010110000000001,0010010000000001,10.3.1,用,ios,类成员函数控制格式,设置域宽、填充字符和精度的成员函数,设置域宽。,int,ios:width,(),返回当前的域宽值。,int,ios:width(int,wid,),此函数用于设置域宽,并返回原来的域宽值。注意,所设置的域宽仅对下一个流输出操作有效,当一次输出操作完成之后,域宽又恢复为,0,。,设置填充字符。,设置显示精度。,面向对象程序设计 第二版,下面举一个例子,说明上述各种成员函数的使用方法:,#include,stdafx.h,#include,iostream.h,void main(),cout,default width is,cout.width,()n;,cout,default fill is,cout.fill,()n;,cout,default precision is,cout.precision,()n;,cout,666 123.45678 n;,cout.precision(3);,cout.width(8);,cout,current width is,cout.width,()n;,cout,current precision is,cout.precision,()n;,cout,666 123.45678 456.78 n;,cout,current width is,cout.width,()n;,cout.fill,(*);,cout.width(8);,cout,666 123.45678 n;,面向对象程序设计 第二版,10.3.1,用,ios,类成员函数控制格式,该程序的输出结果为:,default width is 0,default fill is,default precision is 0,666 123.45678,current width is 8,current precision is 3,666 123.457 456.78,current width is 0,*666 123.457,10.3.1,用,ios,类成员函数控制格式,面向对象程序设计 第二版,从上列输出结果可以看出:,缺省域宽为,0,,即用密集状态输出;缺省的填充字符为空,格;缺省的输出精度为,0,,即按照数据的实际精度输出;,设置了显示精度之后,若数据的实际精度与设置的精度,不一致,则输出方法如下:实际精度大于设置的精度时,,四舍五入后按照设置的精度输出;实际精度小于设置的精,度时,按照实际精度输出;,设置域宽之后,只对其后最接近它的第一个输出有影,响,第一个输出完成后系统立即把域宽置为,0,。,面向对象程序设计 第二版,10.3.1,用,ios,类成员函数控制格式,10.3.2,用控制符控制格式,标准控制符,C+,提供了下列标准的控制符:,dec,:设置十进制转换基格式标志,用于输入,/,输出。,hex,:设置十六进制转换基格式标志,用于输入,/,输出。,oct,:设置八进制转换基格式标志,用于输入,/,输出。,ws,:提取空白字符,仅用于输入。,endl,:插入换行符并刷新流,仅用于输出。,ends,:在串后插入终止空字符,仅用于输出。,flush,:刷新输出流,仅用于输出。,面向对象程序设计 第二版,10.3.2,用控制符控制格式,setbase(int,n),设置转换基格式为,n(,取值,0,,,8,,,10,,或,16),,,缺省时为,0,表示采用十进制,仅用于输出。,resetiosflags(long,f),清除由参数,f,指定的格式位用于输入输出。,setiosflags(long,f),用参数,f,设置格式位,用于输入,/,输出,setfill(int,c),设置填充字符,用于输入,/,输出。,setprecision(int,n),设置浮点数精度为,n,,用于输入,/,输出,setw(int,n),设置域宽为,n,,用于输入,/,输出。,面向对象程序设计 第二版,10.3.2,用控制符控制格式,#include,stdafx.h,#include,iostream.h,#include,iomanip.h,void main(),cout,123setw(5)45688“n”;,cout,123setw(5),setfill,(*)456setw(5)88“n“;,面向对象程序设计 第二版,输出结果为:,123 45688,123*4568*88,10.3.2,用控制符控制格式,用户自定义控制符,C+,除了提供标准的控制符和控制函数之外,也提供了用户自己建立控制符函数的方法。,主要有两个:,第一,,当要对预先未定义的设备进,行操作时,定义自己的控制函数能使得对这类设,备的操作变得方便;,第二,,当多次重复使用几个,相同的控制符时,可以把这些控制符合并在一个,控制函数中,以便于用户使用。,面向对象程序设计 第二版,10.3.2,用控制符控制格式,下面用一个例子说明控制函数的定义和使用:,#,includestdafx.h,#,includeiostream.h,#,includeiomanip.h,ostream,&,setout(ostream,&stream),stream.setf(ios:left,);,stream setw(8),setfill,(*);,return stream;,void main(),cout,first line:setout 25 n;,cout,second line:setout 148”,和输出运算符“,(,istream,&,in,user,-type&,obj,),inobj.item1;,in,obj.itemn,;,return in;,面向对象程序设计 第二版,10.4.1,重载输入运算符,下面举一个重载输入运算符,的例子:,#include,class,ThreeD,int,x,y,z,;,public:,ThreeD(int,i,int,j,int,k),x=i;,y=j;,z=k;,friend,istream,&operator (,istream,&,in,ThreeD,&,obj,);,;,面向对象程序设计 第二版,10.4.1,重载输入运算符,istream,&operator (,istream,&,in,ThreeD,&,obj,),cout,obj.x,;,in,obj.y,;,in,obj.z,;,return in;,void main(),ThreeD,d(2,4,8);,cin,d;,面向对象程序设计 第二版,10.4.1,重载输入运算符,几点注意事项,:,该重载函数的返回类型是,istream,类对象的引,用,返回引用的目的在于,把几个输入运算符,“”,放在同一条输入语句中时,该重载函数仍能,正确工作。,重载运算符函数,operator“”,的第二个参数,必须是一个引用。,该运算符函数有两个参数,第一个参数是对,istream,类对象的引用,它出现在运算符“,”,的,左边,第二个参数是出现在运算符右边的自定义,类型对象。,面向对象程序设计 第二版,10.4.2,重载输出运算符,用友元函数重载输出运算符,”“,来实现用户自定义类型对象的输出。定义运算符函数的格式如下:,ostream,&operator(,ostream,&,out,user,-type&,obj,),outobj.item1,;,out,obj.itemn,;,return out;,面向对象程序设计 第二版,10.4.2,重载输出运算符,下面举一个例子说明重载输出运算符的方法:,#,includestdafx.h,#,includeiostream.h,class,ThreeD,int,x,y,z,;,public:,ThreeD(int,i,int,j,int,k),x=i;,y=j;,z=k;,friend,ostream,&operator (,ostream,&,out,ThreeD,&,obj,);,;,面向对象程序设计 第二版,10.4.2,重载输出运算符,ostream,&operator (,ostream,&,out,ThreeD,&,obj,),out,obj.x,;,out,obj.y,;,out,obj.z,n;,return out;,void main(),ThreeD,d1(11,22,33),d2(45,56,67);,cout,d1”,和输出运算符“,”,和输出运算符,“,”,。例如,把一个整数、一个浮点数和一个字符串写到文件,data,中,程序如下:,#include,stdafx.h,#include,iostream.h,#include,fstream.h,main(),ofstream,out(data,);,if(!out,),cout,can not open file data.;,return 0;,out 256 198.69 C+Languagen;,out.close,();,return 1;,10.5.2,文件的读写,面向对象程序设计 第二版,特殊格式文件的读写,10.5.2,文件的读写,面向对象程序设计 第二版,图,10.3,一种特殊格式文件的结构示意图,#include,stdafx.h,#include,fstream.h,#include,conio.h,#include,ctype.h,#include,stdlib.h,int,main(int,argc,char*,argv,),char,ch,;,char p225;,char*,p_title,=,特殊格式的文件,;,char*,p_total,=,字符总数为:,;,char*,p_total_alpha,=,字母总数为:,;,char*,p_total_number,=,数字总数为:,;,char*,p_input,=,输入的字符串为:,;,char*,p_blank,=;/,先将不可知的数据置成空格(此处为,4,个),int,total=0;,int,total_number,=0;,int,total_alpha,=0;,ofstream,outfile,;,面向对象程序设计 第二版,10.5.2,文件的读写,outfile.open(iotext.dat,);/,以此种方式打开的文件:如果没有这个文件,/,(,iotext.dat,),则创建这个文件;如果文件已,/,经存在,则重写这个文件(清空原内容),if(!outfile.is_open,()/,这是一种安全的操作,以确保文件的建立和打开,cout,文件创建,/,打开失败!,endl,;,return 0;,outfile.write(p_title,30);/,输出,p_title,中内容,限制,30,个字节,outfile.write(p_total,20);,outfile.write(p_blank,6);,outfile.write(p_total_alpha,20);,outfile.write(p_blank,6);,outfile.write(p_total_number,20);,outfile.write(p_blank,6);,outfile.write(p_input,20);,cout,请输入字符串,:,endl,;,while(ch,=,getche,()!=13)/,从键盘获得字符,如果是回车(其,ASCII,码为,13,)就结束,否则写入文件,if(isalpha(ch,)/,判断,ch,是否为字母,total_alpha,+;/,字母个数,+1,if(isdigit(ch,)/,判断,ch,是否为数字,total_number,+;/,数字个数,+1,面向对象程序设计 第二版,10.5.2,文件的读写,outfile.write(,total+;,ch,=0;,outfile.write(/,给输入的字符串增加一个结束标志,cout,n,输入完毕,endl,;,outfile.seekp(50);/,调整文件指针,使其指向图中第,3,个块,outfile,total;/,向第,3,个块中写入字符总数,outfile.seekp(76);,outfile,total_alpha,;,outfile.seekp(102);,outfile,total_number,;,outfile.close,();/,文件操作结束后必须关闭文件,否则数据可能丢失,cout,输出内容,:,endl,;,ifstream,infile,;,infile.open(iotext.dat,);/,打开指定的文件,if(!infile.is_open,(),cout,文件创建,/,打开失败!,endl,;,return 0;,面向对象程序设计 第二版,10.5.2,文件的读写,/*,按顺序依次读取限定长度的字符串(图中的,1,8,块),并在屏幕,上输出这些字符串*,/,infile.read(p2,30);,cout,p2,endl,;,infile.read(p2,20);,cout,p2,endl,;,infile.read(p2,6);,cout,p2,endl,;,infile.read(p2,20);,cout,p2,endl,;,infile.read(p2,6);,cout,p2,endl,;,infile.read(p2,20);,cout,p2,endl,;,infile.read(p2,6);,cout,p2,endl,;,infile.read(p2,20);,cout,p2,endl,;,面向对象程序设计 第二版,10.5.2,文件的读写,10.5.2,文件的读写,/*,依次从文件中读取键入的所有字符(图中的第,9,个块),并逐个在屏,幕上显示*,/,char ch1=,infile.eof,();/,获得文件结束标志,while(1),infile.read(,if(ch,=ch1)break;/,如果文件结束就跳出循环,cout,ch,;,cout,endl,;,infile.close,();,return 0;,面向对象程序设计 第二版,10.6,小结,所谓流就是数据从源到漏的流动,也可以把流简化地理,解成,提供字符的输入流或收集字符的输出流,某些流既,是输入流又是输出流。,istream,和,ostream,这两个流类提供了流库的主要输入,/,输,出界面,是使用流库的关键,应该着重学习掌握。,在建立文件流的时候,需要使用面向文件流类的构造函,数。每个文件流类都定义了四个构造函数,或用于创建未,打开的文件流,或用于创建已打开的文件流。创建了未打,开的文件流之后,还需要使用成员函数,open,来打开它。,面向对象程序设计 第二版,思考题,向硬盘上输出一个数据文件,要求:,1.,包含,3,个记录,且各个记录的长度不定,2.,在每个记录的前面加上记录号,分别是,01,,,02,,,03,3.,在每个记录的前面的记录号后面还要加上本记录的长度,4.,在文件的最前面加上文件名,,myfile.dat,如,:myfile.dat,01,32,记录,01,的数据,,02,67,记录,02,的数据,,03,67,记录,03,的数据。,面向对象程序设计 第二版,
展开阅读全文