面向对象程序设计C++——第8章输入/输出流对象2主要内容流无格式输入/输出输入/输出的格式控制自定义类型对象的输入输出文件的输入/输出3分析问题C++没有定义任何用于执行输入或输出的语句,但可以使用C语言中的标准I/O函数printf()和scanf()来解决此问题。printf()与scanf()存在两个缺点:非类型安全不可扩充性4C++使用类型安全的I/O流操作。不同类型的I/O流操作都是重载的,没有定义过I/O功能的类型不具备I/O操作的能力。C++标准库既可作为标准数据类型数据的I/O,也能用于自定义类型的对象的I/O,这种扩展性是C++最有价值的特点之一。C++用输入输出流来解决这个问题。5流所谓流(stream)是指数据从一个位置流向另一个位置。流是字节的序列。输入/输出是一种数据传递操作,可以看作字符序列在计算机内存与外设之间的流动,C++将数据从一个对象到另一个对象的流动抽象为“流”。流动的方向不同,构成输入/输出流,即I/O流。6I/O流在C++程序中,数据可以从键盘流入到程序,也可以从程序流向屏幕或磁盘文件。从流中获取数据的操作称为提取操作,向流中添加数据的操作称为插入操作。数据的输入/输出就是通过I/O流来实现的。7编译系统已经以运算符或函数的形式做好了对标准外设(键盘、屏幕、打印机、文件)的接口,使用时只需按照要求的格式调用即可。cinx;coutx;内存键盘文件光笔....输入流显示器文件打印机...输出流8I/O流类库的层次结构C++编译系统提供的I/O流类库含有两个平行基类:streambufiosios类有4个直接派生类:输入流类istream输出流类ostream文件流类fstreambase串流类strstreambase9I/O流类库的头文件iostream:I/O流类库的最主要的头文件,它包括操作所有I/O所需的基本信息,还包括cin、cout、cerr和clog共4个对象。iomanip:包含带参数的流操纵算子的有关信息。fstream:包含对文件I/O操作的有关信息。strstream:包含对内存格式化I/O操作的有关信息。stdiostream:包含混合使用C和C++风格的I/O操作的有关信息。10intmain(){floata,b,c,disc;cout“pleaseinputa,b,c:”;cinabc;if(a==0)cerr“aisequaltozero,error!”endl;elseif((disc=b*b-4*a*c)0)cerr“disc=b*b-4*a*c0”endl;else{cout“x1=”(-b+sqrt(disc))/(2*a)endl;cout“x2=”(-b-sqrt(disc))/(2*a)endl;}return0;}1:pleaseinputa,b,c:023aisequaltozero,error!2:pleaseinputa,b,c:523disc=b*b-4*a*c03:pleaseinputa,b,c:12.51.5x1=-1x2=-1.511无格式输入/输出无格式输入/输出就是按系统预定义的格式进行的输入/输出。按默认约定,每个C++程序都能使用标准I/O流,如标准输入、标准输出。cin用来处理标准输入,即键盘输入;cout用来处理标准输出,即屏幕输出。它们被定义在iostream头文件中。在使用cout和cin前,要用编译预处理命令将所使用的头文件包含到源程序中,其格式如下:#includeiostream12无格式输出“”是预定义的插入运算符,作用在流类对象cout上,实现默认格式的屏幕输出。使用cout输出表达式值到屏幕上的格式如下:coutE1E2…Em;其中,E1、E2、…、Em为均为表达式。用“cout”输出基本类型的数据时,可以不必考虑数据是什么类型,系统会判断数据的类型,并调用与之匹配的运算符重载函数。13无格式输出cout是ostream流类的对象,它在iostream头文件中作为全局对象定义,其格式如下:ostreamcout(stdout);其中,stdout表示标准输出设备名(屏幕)。14无格式输入“”是预定义的提取运算符,作用在流类对象cin上,实现默认格式的键盘输入。使用cin将数据输入到变量的格式如下:cinV1V2…Vn;其中,V1、V2、…、Vn都是变量。功能是暂停执行程序,等待用户从键盘输入数据,各数据间用空格或Tab键分隔,输入数据类型要与接受变量类型一致,输完后,按回车键结束。15无格式输入cin是istream流类的对象,它在iostream头文件中作为全局对象定义,其格式如下:istreamcin(stdin);标准输入设备名(键盘)16输入输出的格式控制C++提供了两种格式化输入/输出方式:一种是用ios类成员函数进行格式化输入输出另一种是用专门的操作符函数进行格式化输入输出17用ios类成员函数格式化ios类成员函数主要是通过对状态标志、输出宽度、填充字符以及输出精度的操作来完成输入/输出格式化。输入/输出的格式由各种状态标志来确定,在ios类中定义为枚举量。枚举量定义在ios类中,因此引用时必须包含ios::前缀。使用时应该全部用符号名,绝不要用数值。18用ios成员函数对状态标志进行操作ios类有3个成员函数可以对状态标志进行操作,并且定义了一个long型数据成员记录当前状态标志。这些状态标志可用位或运算符“|”进行组合。用setf函数设置状态标志,其一般格式如下:longios::setf(longflags)19用ios成员函数对状态标志进行操作清除状态标志用unsetf函数清除状态标志,其一般格式如下:longios::unsetf(longflags)20用ios成员函数对状态标志进行操作用函数flags取状态标志有两种形式,其格式分别如下:longios::flags()//返回与流相关的当前状态标志值longios::flags(longflag)//将流的状态标志值设置为flag,并返回设置前的状态标志值。21用ios成员函数对状态标志进行操作以上三组函数必须用流类对象(cin或cout)来调用,其格式如下:流对象名.函数名(ios::状态标志)cout.setf(ios::showpos);cout.setf(ios::scientific);cout.setf(ios::showpos|ios::scientific);2200000010000000010011001000100001001000100010000100100010001000010000100000000000voidshowflags(longf);intmain(){longf;f=cout.flags();//取当前状态标志showflags(f);//显示状态值cout.setf(ios::showpos|ios::scientific|ios::fixed);//追加状态标志f=cout.flags();//取当前状态标志showflags(f);//显示状态值cout.unsetf(ios::scientific);//从状态标志中去掉scientificf=cout.flags();//取当前状态标志showflags(f);//显示状态值f=cout.flags(ios::hex);//重新设置状态标志showflags(f);f=cout.flags();//取当前状态标志showflags(f);return0;}voidshowflags(longf){longi;for(i=0x8000;i;i=i1)//用右移方式使i中的值为1的位不断右移if(i&f)cout1;//判断f中的某一位是否为1elsecout0;coutendl;}例8-4示例对状态标志的操作。23用ios成员函数设置输出宽度设置输出宽度函数有两种形式,其格式分别如下:intios::width(intlen)intios::width()第一种形式是设置输出宽度,并返回原来的输出宽度;第二种形式是返回当前输出宽度,默认输出宽度为0。只对其后的第一个输出项有效。24设置填充字符填充字符的作用是当输出值不满输出宽度时用填充字符来填充,默认填充字符为空格。它与width()函数配合使用,否则没有意义。设置填充字符函数有两种形式,其格式分别如下:charios::fill(charch)charios::fill()第一种形式是重新设置填充字符,并返回设置前的填充字符;第二种形式是返回当前的填充字符。25设置输出精度设置浮点数输出精度有两种形式,其格式分别如下:intios::precision(intp)intios::precision()第一种形式是重新设置输出精度,并返回设置前的输出精度;第二种形式是返回当前的输出精度。默认输出精度为6。26以上三组函数必须用流类对象(cin或cout)来调用。27width:08(newwidth)fillingwordis:(ASCIIcode32)*(42)(newfillingword)precision:6123.45679(example)8(newprecision)intmain(){inti;i=cout.width();coutwidth:iendl;cout.width(8);coutcout.width()(newwidth)endl;charc;c=cout.fill();coutfillingwordis:c(ASCIIcode(int)c)endl;cout.fill('*');coutcout.fill()((int)cout.fill())(newfillingword)endl;intj;j=cout.precision();coutprecision:jendl;cout.precision(8);cout123.456789(example)endl;coutcout.precision()(newprecision)endl;return0;}例8-6示例设置输出宽度、填充字符、输出精度。28用操作符函数格式化为了不直接以标志位的方式去处理流的状态,c++标准库提供了标准的操作符函数专门操控这些状态。这组函数不属于任何类成员,定义在iomanip头文件中。将它们用在提取运算符“”或插入运算符“”后面来设定输入/输出格式,即在读写对象之间插入一个修改状态的操作。其中有些函数没有参数,所以又叫操作符。29设置输入/输出宽度函数setw(int)用整型参数来制定输入/输出域的宽度。使用时只对其后一项输入/输出有效。当用于输出时,若实际宽度小于设置宽度时,数据向右对齐,反之则按数据的实际宽度输出。当用于输入时,若输入的数据宽度超过设置宽度时,超出的数据部分被截断而被作为下一项输入内容。3012345678123456781234512345i:10#includeiostream#includeiomanipusingnamespacestd;intmain(){char*p=12345,*q=678;charf[4],g[4];//最后一位为'\0'inti=10;coutpsetw(6)qsetw(4)pqendl;//设置输出宽度cinsetw(4)fg;//设置输入宽度coutfendlgendli:iendl;return0;}例8-7用操作符函