第13章输入输出流13.1C++的输入和输出13.2标准输出流13.3标准输入流13.4文件操作与文件流13.5字符串流计算机科学与技术学院13.1C++的输入和输出13.1.1输入输出的含义操作系统的输入输出每一个与主机相连的输入输出设备都被看作一个文件。除了以终端为对象进行输入和输出外,还经常用磁盘(光盘)作为输入输出对象,磁盘文件既可以作为输入文件,也可以作为输出文件。计算机科学与技术学院C++输入输出包括:(1)对系统指定的标准设备的输入和输出。即从键盘输入数据,输出到显示器屏幕。这种输入输出称为标准的输入输出,简称标准I/O。(2)以外存磁盘文件为对象进行输入和输出,即从磁盘文件输入数据,数据输出到磁盘文件。以外存文件为对象的输入输出称为文件的输入输出,简称文件I/O。(3)对内存中指定的空间进行输入和输出。通常指定一个字符数组作为存储空间(实际上可以利用该空间存储任何信息)。这种输入和输出称为字符串输入输出,简称串I/O。C++系统提供了庞大的I/O类库,调用不同的类去实现不同的功能。在C语言中,用printf和scanf进行输入输出,往往不能保证所输入输出的数据是可靠的、安全的。在C++的输入输出中,C++的I/O操作是类型安全(typesafe)的。C++的I/O操作是可扩展的,不仅可以用来输入输出标准类型的数据,也可以用于用户自定义类型的数据。C++通过I/O类库来实现丰富的I/O功能13.1.2C++的I/O对C的发展——类型安全和可扩展性计算机科学与技术学院13.1.2C++的I/O对C的发展——类型安全和可扩展性在C语言中,用printf和scanf进行输入输出,往往不能保证所输入输出的数据是可靠的、安全的。在C++的输入输出中,因此C++的I/O操作是类型安全(typesafe)的。C++的I/O操作是可扩展的,不仅可以用来输入输出标准类型的数据,也可以用于用户自定义类型的数据。C++通过I/O类库来实现丰富的I/O功能计算机科学与技术学院13.1.3C++的输入输出流流的含义指由若干字节组成的字节序列,这些字节中的数据按顺序从一个对象传送到另一对象。流表示了信息从源到目的端的流动。在输入操作时,字节流从输入设备(如键盘、磁盘)流向内存,在输出操作时,字节流从内存流向输出设备(如屏幕、打印机、磁盘等)。流中的内容可以是ASCII字符、二进制形式的数据、图形图像、数字音频视频或其他形式的信息。实际上,在内存中为每一个数据流开辟一个内存缓冲区,用来存放流中的数据。流是与内存缓冲区相对应的,或者说,缓冲区中的数据就是流。在C++中,输入输出流被定义为类。C++的I/O库中的类称为流类(streamclass)。用流类定义的对象称为流对象。cincout就是流类定义的对象1.iostream类库中有关的类1)istreamostreamiostream类继承层次见图2)ifstreamofstreamfstream继承层次见图3)C++I/O类库继承层次见图2.与iostream类库有关的头文件iostream:包含了对输入输出流进行操作所需的基本信息。fstream:用于用户管理的文件的I/O操作。strstream:用于字符串流I/O。stdiostream:用于混合使用C和C++的I/O机制时。iomanip:在使用格式化I/O时应包含此头文件。3.在iostream头文件中定义的流对象1)在iostream头文件中定义的类有:ios,istream,ostream,iostream,istream_withassign,ostream_withassign,iostream_withassign等。2)iostream.h包含了对输入输出流进行操作所需的基本信息。在iostream.h头文件中不仅定义了有关的类,还定义了4种流对象:cin是istream_withassig的对象cout是ostream_withassign的对象cerr和clog是ostream_withassign的对象iostream.h中定义形式ostreamcout(stdout)4.在iostream头文件中重载运算符1)在iostream头文件中对“”和“”进行了重载2)对于不同的标准数据类型要分别进行重载,如ostreamoperator(int);//用于向输出流插入一个int数据ostreamoperator(float);//用于向输出流插入一个float数据ostreamoperator(char);//用于向输出流插入一个char数据ostreamoperator(char*);//向输出流插入一个字符串数据等。3)理解运算符“”和“”它们指出了数据移动的方向例如a箭头方向表示把数据放入a中。a箭头方向表示从a中拿出数据。标准输出流是流向标准输出设备(显示器)的数据。13.2标准输出流1.cout流对象cout是consoleoutput(1)cout不是C++预定义的关键字,它是ostream流类的对象,在iostream中定义。(2)用“cout”输出基本类型的数据时,可以不必考虑数据是什么类型,系统根据类型选择调用与之匹配的运算符重载函数。(3)cout流在内存中对应开辟了一个缓冲区,用来存放流中的数据,当向cout流插入一个endl时,不论缓冲区是否已满,都立即输出流中所有数据,然后插入一个换行符,并刷新流(清空缓冲区)。(4)在iostream中只对“”和“”运算符用于标准类型数据的输入输出进行了重载,但未对用户声明的类型数据的输入输出进行重载。13.2.1cout,cerr和clog流2.cerr流对象1)cerr流对象是标准错误流。cerr流已被指定为与显示器关联。2)cerr的作用是向标准错误设备(standarderrordevice)输出有关出错信息。3)cerr与标准输出流cout的作用和用法差不多。但有一点不同:cout流通常是传送到显示器输出,但也可以被重定向输出到磁盘文件,而cerr流中的信息只能在显示器输出。例13.1有一元二次方程ax2+bx+c=0,其一般解为x1,2=(-b±b2-4ac)/2a,但若a=0,或b2-4ac0时,用此公式出错。编程序,从键盘输入a,b,c的值,求x1和x2。如果a=0或b2-4ac0,输出出错信息。#includeiostream#includecmathusingnamespacestd;intmain(){floata,b,c,disc;cout″pleaseinputa,b,c:″;cinabc;if(a==0)cerr″aisequaltozero,error!″endl;//将有关出错信息插入cerr流elseif((disc=b*b-4*a*c)0)cerr″disc=b*b-4*a*c0″endl;//将有关出错信息插入cerr流else{cout″x1=″(-b+sqrt(disc))/(2*a)endl;cout″x2=″(-b-sqrt(disc))/(2*a)endl;}return0;}运行情况如下:pleaseinputa,b,c:023↙aisequaltozero,error!pleaseinputa,b,c:523↙sc=b*b-4*a*c0pleaseinputa,b,c:12.51.5↙x1=-1x2=-1.53.clog流对象1)clog流对象也是标准错误流,它是consolelog的缩写。2)clog作用和cerr相同,都是在终端显示器上显示出错信息。区别:cerr是不经过缓冲区,直接向显示器上输出有关信息,而clog中的信息存放在缓冲区中,缓冲区满后或遇endl时向显示器输出。1.使用控制符控制输出格式1)输出数据的控制符见书中表13.3。2)控制符是在头文件iomanip中定义的,因而程序中应当包含iomanip。13.2.2格式输出例13.2用控制符控制输出格式。#includeiostream#includeiomanip//不要忘记包含此头文件usingnamespacestd;intmain(){inta;cout″inputa:″;cina;cout″dec:″decaendl;//以十进制形式输出整数cout″hex:″hexaendl;//以十六进制形式输出整数acout″oct:″setbase(8)aendl;//以八进制形式输出整数achar*pt=″China″;//pt指向字符串″China″coutsetw(10)ptendl;//指定域宽为10,输出字符串coutsetfill(′*′)setw(10)ptendl;//指定域宽10,以′*′填充doublepi=22.0/7.0;//计算pi值coutsetiosflags(ios::scientific)setprecision(8);//按指数形式输出,8位小数cout″pi=″piendl;//输出pi值cout″pi=″setprecision(4)piendl;//改为4位小数cout″pi=″setiosflags(ios::fixed)piendl;//改为小数形式输出return0;}运行结果如下:inputa:34↙(输入a的值)dec:34(十进制形式)hex:22(十六进制形式)oct:42(八进制形式)China(域宽为10)*****China(域宽为10,空白处以′*′填充)pi=3.14285714e+00(指数形式输出,8位小数)pi=3.1429e+00(指数形式输出,4位小数)pi=3.143(小数形式输出,精度仍为4)2.用流对象的成员函数控制输出格式1)用于控制输出格式的常用的成员函数见书中表13.4。2)流成员函数setf和控制符setiosflags括号中的参数表示格式状态,它是通过格式标志来指定的。3)格式标志在类ios中被定义为枚举值。因此在引用这些格式标志时要在前面加上类名ios和域运算符“::”。格式标志见书中表13.5。例13.3用流控制成员函数输出数据。#includeiostreamusingnamespacestd;intmain(){inta=21cout.setf(ios::showbase);//显示基数符号(0x或0)cout″dec:″aendl;//默认以十进制形式输出acout.unsetf(ios::dec);//终止十进制的格式设置cout.setf(ios::hex);//设置以十六进制输出的状态cout″hex:″aendl;//以十六进制形式输出acout.unsetf(ios::hex);//终止十六进制的格式设置cout.setf(ios::oct);//设置以八进制输出的状态cout″oct:″aendl;//以八进制形式输出acout.unseft(ios::oct);char*pt=″China″;//pt指向字符串″China″cout.width(10);//指定域宽为10coutptendl;//输出字符串cout.width(10);//指定域宽为10cout.fill(′*′);//指定空白处以′*′填充coutptendl;//输出字符串doublepi=22.0/7.0;//输出pi值cout.setf(ios::scientific);//指定用科学记数法输出cout″pi=″;//输出″pi=″cout.width(14);//指定域宽为14coutpiendl;//输出pi值cout.unsetf(ios::scientific);//终止科学记数法状态cou