第14章 输入与输出流类库.docx
- 文档编号:29227806
- 上传时间:2023-07-21
- 格式:DOCX
- 页数:22
- 大小:28.17KB
第14章 输入与输出流类库.docx
《第14章 输入与输出流类库.docx》由会员分享,可在线阅读,更多相关《第14章 输入与输出流类库.docx(22页珍藏版)》请在冰豆网上搜索。
第14章输入与输出流类库
第14章输入与输出流类库
C++的I/O流类,是目前最常用的I/O系统。
本章介绍C++输入与输出流类库。
通过本章的学习,读者可以了解怎样使用C++面向对象的输入/输出流,能够格式化输入和输出,了解I/O流类的层次结构,了解怎样输入/输出用户自定义类型的对象,能够建立用户自定义的流操作符,能够确定输入/输出操作的成功与失败,能够把输出流连到输入流上。
14.1I/O流类的结构(略)
14.2文件流类
C++语言把每个文件都看成一个有序的字节流。
每个文件或者以文件结束符结束,或者在特定的字节号处结束(该字节号通常记录在由系统维护和管理的数据结构中)。
当打开一个文件时,该文件就和某个流关联起来。
系统自动生成cin、cout、cerr、clog对象,流使用这些对象所关联的特定文件或输入/输出设备和程序之间建立通信通道。
要在C++中进行文件处理,就要包含头文件
生成这些流类的对象即可打开文件。
这些流类分别从istream、ostream和iostream类派生。
其层次结构如图14.2。
图14.2文件流类的继承关系
在C++中,要定义一个文件流类对象,必须规定文件名和打开方式。
类ofstream用于执行文件输出,该类有几个构造函数,其中最有用的是:
ofstream:
:
ofstream(char*pFileName,//指向要打开的文件名字符串
intnMode=ios:
:
out,//打开方式
intnProt=filebuf:
:
openprot);//文件保护方式
nMode参数是打开方式,它的含义见表14.1
表14.1文件打开选择项
标志
含义
ios:
:
app
将所有输出写入文件尾
ios:
:
ate
打开文件以便输出,并移到文件末尾(通常用于添加数据),数据可以写入文件中的任何地方
ios:
:
in
打开文件以便写入(ifstream默认)
ios:
:
out
打开文件以便输出(ofstream默认)
ios:
:
trunc
删除文件现有内容(是ios:
:
out的默认操作)
ios:
:
nocreate
如果文件不存在,则文件打开失败
ios:
:
noreplace
如果文件存在,则文件打开失败
nProt是文件保护方式,它的选择项见表14.2。
表14.2文件保护方式选择项
标志
含义
filebuf:
:
openprot
兼容共享方式
filebuf:
:
sh_none
独占,不共享
filebuf:
:
sh_read
允许读共享
file:
:
sh_write
允许写共享
由于C++把文件看作是无结构的字节流,所以为了在文件中记录特定结构的内容,必须给文件加上记录结构。
下面的程序演示了班级学生成绩表,学号作为记录关键字,文件按学号顺序建立和维护。
假定用户按学号顺序键入记录,程序将把键入的记录保存并写入文件。
程序示例如下。
例14.4文件流操作实例
//演示文件流操作
#include"stdafx.h"
#include
#include
#include
intmain()
{
intregNumber;
charname[30];
floatgrade;
//使用ofstream类的构造函数打开文件
ofstreamoutGradeFile("C:
\\grade.dat",ios:
:
out);
//也可以先创建输出流类对象,再用open操作打开文件
//ofstreamoutGradeFile;
//outGradeFile.open("C:
\\grade.dat",ios:
:
out);
if(!
outGradeFile){
cerr<<"文件不能被打开!
"< exit (1);//函数原形定义在stdlib.h中 } cout<<"请输入学号,姓名,和成绩,\n" <<"按输入文件结束符结束。 \n? "; while(cin>>regNumber>>name>>grade){ outGradeFile< <<""< cout<<"? "; } outGradeFile.close(); ifstreaminGradeFile("C: \\grade.dat",ios: : in); //也可以先创建输入流类对象,再用open操作打开文件 //ifstreaminGradeFile; //inGradeFile.open("C: \\grade.dat",ios: : in); cout<<"? "; while(inGradeFile>>regNumber>>name>>grade){ cout< <<""< cout<<"? "; } inGradeFile.close(); return0;//ofstream的析构函数将关闭文件 } 程序运行结果如下: 请输入学号,姓名,和成绩, 按输入文件结束符结束。 ? 123aaa78 ? 234bbb89 ? 345ccc69 ? ^Z ? 123aaa78 ? 234bbb89 ? 345ccc69 上例中,对于文件名要说明其路径,斜杠要双写,因为编译器理解下的斜杠是字符转换符。 这和包含头文件时的路径不一样,因为包含头文件是由编译预器处理的。 文件打开时,对于使用ofstream类构造对象时,其打开方式默认为ios: : out|ios: : trunc,即该文件每次打开,如果原先存在,则都会先被清空内容,否则就新建。 如果要打开二进制文件,写方式,输出到文件尾,可以如下操作: ofstreambfile(“binfile”,ios: : binary|ios: : ate); 也可以生成oftream对象而不打开特定文件,而在后面再将文件与对象相连接。 可以如下操作: ofstreamoutFile; outFile.open(“abc.dat”,ios: : out); 如果需要打开一个输入文件,从文件中读取数据可以如下操作: ifstreammyinf(“C: \\grade.dat”,ios: : nocreate); if(myinf.fail()) { cerr<<”打开文件出错! \n”; return; } myinf>>regNumber>>name>>grade; … 对于打开文件是否操作成功,可以使用重载的ios运算符成员函数! 操作符确定打开是否成功,如果打开操作的流将failbit或badbit置位,则条件(! outGradeFile)返回非0值(true);也可以通过判断fail()成员函数来确定打开文件是否出错。 如果打开文件同时用于输入和输出,则可以如下操作: fstreammyinout(“abc.dat”,ios: : in|ios: : out); 用fstream打开的文件,打开方式不能默认。 14.3串流类(不讲) ostrstream、istrstream、strstream是串流类,在strstrea.h中定义。 其中,strstream类是从ostrstream和istrstream类多重继承而来的子类。 要定义一个串流类对象,须提供字符数组和数组大小。 类istrstream用于串流输入,该类有几个构造函数,其中最有用的是: istrstream: : istrstream(constchar*pch); istrstream: : istrstream(constchar*pch,intnLength); 第一个参数指出字符串数组,第二个参数说明数组大小。 当size为0时,表示把istrstream类对象连接到由pch指向的以空字符结束的字符串。 类ostrstream用于执行串流输出,该类也有几个构造函数,其中最有用的是: ostrstream: : ostrstream(char*pch,intnLength,intnMode=ios: : out); 第一个参数指出字符串数组,第二个参数说明数组大小,第三个参数指出打开方式。 下面的实例演示了如何使用串流输入输出功能。 例14.5串流输入输出功能实例 //演示串流输入输出功能 #include #include #include char*parseString(char*pch) { intnumber; floatbalance; //计算需要构造的串流类的长度 //strlen返回字符串长度,其定义包含在string.h中 intnLength=strlen("帐号: ") +strlen("收支: ") +strlen(pch); istrstreaminp(pch,0);//ios: : in方式,读到null结束 inp>>number>>balance;//从串流中读入一个整数和浮点数 char*pBuffer=newchar[nLength]; ostrstreamoutp(pBuffer,nLength);//ios: : out方式,字串长度为计算出的nLength, //刚好满足输出到pBuffer中的长度要求 outp<<"帐号: "< <<"收支: "< //注意该处如果写入超出pBuffer空间长度的字符, //超出部分将不会被写入 returnpBuffer; } intmain() { char*pch="1001125.45"; char*pBuf=parseString(pch); cout< delete[]pBuf; return0; } 演示结果如下: 帐号: 1001收支: 125.45 在函数parseString()中,先定义了一个输入串流对象inp,将输入设备pch中的字符输入到了一个整数和一个浮点数中,然后,定义了一个输出串流对象outp,将提示信息和这两个变量输出到outp连接的输出设备(实际为一字符串空间)pbuffer中。 注意语句: outp<<"帐号: "< <<"收支: "< 它同时也将提示信息“帐号: ”、“收支: ”也写入到了输出设备pbuffer中。 14.4格式控制(浏览) C++提供了大量用于执行格式化输入/输出的流格式控制以及流对象成员函数。 比如: 设置域宽、设置精度、设置和清除格式化标志、设置域填充符、刷新流、在输出流中插入换行符并刷新该流、在输出流中插入空字符、跳过输入流中的空白字符等等。 控制符是在头文件iomanip.h中定义的对象,可以将它们直接插入流中,来控制流输入/输出的格式。 使用成员函数控制,则需要在格式化输出之前调用相关格式设置成员函数。 14.4.1整数流的基数控制 整数通常被解释为十进制(基数为10)整数。 可以通过在流中插入控制符而改变流中整数的基数。 插入控制符hex可设置成十六进制基数;插入控制符oct可设置成八进制基数、插入控制符dec可恢复十进制基数。 同样可以使用成员函数flags来设置整数流的基数。 下面的程序演示了这些控制符和成员函数的用法。 例14.6整数流格式控制实例 //演示整数流格式控制 #include #include intmain() { intn; cout<<"输入一个十进制整数: "; cin>>n; cout< " < < " < cout.flags(10); cout<<"恢复十进制为: " < return0; } 演示结果如下: 输入一个十进制整数: 15 15的十六进制为: f 15的八进制为: 17 恢复十进制为: 15 14.4.2设置浮点数精度 控制浮点流的精度,可以使用控制符setprecision或成员函数precision来格式化小数点后面的位数。 语句: cout< 和语句: cout.precision(4); cout< 起到了同样的效果,都将浮点型数据fValue按精确到小数点后面4位数输出。 14.4.3设置域宽 成员函数ios: : width设置当前的域宽(即输入输出的字符数)并返回以前设置的域宽。 如果显示数据所需的宽度比设置的域宽小,空位用填充字符填充。 如果显示数据所需的宽度比设置的域宽大,显示数据并不会被截断,而是输出所有位,但可能会出现乱码。 控制符setw也可以用来设置域宽。 它们的用法如下: cout.width(8); cout<<10; 上面的语句将在输出10之前输出6个空格(默认填充符)。 cout< 这条语句可以起到同样的效果。 需要注意的是setw(n)或width(n)在下一个域输出后,域宽回到原先的默认值。 setw()的默认域宽为0,意思是按输出对象的表示宽度输出。 下面的语句中,20将紧挨着10输出。 cout< 14.4.4设置填充符 可以使用成员函数fill或控制符setfill来改变所要填充的字符。 cout.fill(‘*’); cout< 输出结果为: ******10 由于输出域宽为8,所以在10前面填充了6个*。 下面的语句将起到同样的效果。 cout< 14.4.5用户自定义流格式控制符 C++提供了非常多的流格式控制符和成员函数来格式化流输入/输出。 上面仅介绍了常用的几种控制和成员函数的使用方法。 在这里,再简单介绍一种用户自定义流控制符的方法。 先看下面的程序示例: 例14.7用户自定义流格式控制符实例 //演示用户自定义流格式控制符 #include //警告符,输出时会发出系统警告声音 ostream&bell(ostream&output){returnoutput<<'\a';} //回车符 ostream&ret(ostream&output){returnoutput<<'\r';} //水平制表符,是光标移到下一个制表位 ostream&tab(ostream&output){returnoutput<<'\t';} //换行符 ostream&endLine(ostream&output) { returnoutput<<'\n'< } intmain() { cout<<"测试制表符: "< <<'a'< <<"测试回车符和警告符: " < cout< cout< return0; } 演示结果如下: 测试制表符: abc 测试回车符和警告符: -----.. 在上面的例子中,演示了如何建立和使用新的流控制符bell、ret、tab和endLine。 需要注意的是,程序用endLine插入输出了换行符,然后输出7个省略号.......,输出系统警告声,再插入ret回车,再输出5个破仄号-----,结果省略号被破仄号覆盖了前面部分。 14.5流类成员函数的使用 在C++中,经常使用cin、cout来做输入/输出。 比较常用的I/O流的成员函数有get、getline、put、eof等。 Get函数原型有很多个,比较常用的函数原型有: charistream: : get(); istream&istream: : get(char*pch,intnCount,chardelim=’\n”); istream&get(char&rch); 不带参数的get函数从指定的输入流中读取一个字符(包括空白字符),并返回该字符,当遇到输入流中的文件结束符时,返回EOF。 带一个字符型参数的get成员函数自动读取一个字符(包括空白字符)到字符型参数中。 当遇到文件结束符时,返回0,否则返回对istream对象的引用。 带三个参数的get成员函数的参数分别是接收字符的字符数组、字符数组的大小和分隔符(默认值为’\n’)。 该函数或者在读取比指定的最大字符数少一个字符后结束,或者在遇到分隔符时结束。 下面的程序循环读入字符,直到用户键入一个Y字符,或遇到文件结束符(在UNIX与Macintosh上,文件结束符为 例14.8I/O流成员函数的使用实例 //演示I/O流的get、put、eof成员函数的使用 #include #include intmain() { charch; while(! cin.eof()) { ch=cin.get(); ch=toupper(ch); if(ch=='Y') { cout.put(ch); break; } cout< } return0; } 上例中使用了toupper函数将键入字符全部转换成大写字母后赋值给ch,使用该函数应包含头文件ctype.h。 使用带三个参数的get函数,会比较安全。 例如下面这种代码: istreamfin(“abc.dat”); charbuf[80]; fin>>buf; 应改成: istreamfin(“abc.dat”; charbuf[80]; fin.get(buffer,80); getline成员函数原型为: getline(char*pch,intnCount,chardelim=’\n”); getline函数与带三个参数的get函数类似,它读取一行信息到字符数组中,然后插入一个空字符。 所不同的是,getline要去除输入流中的分隔符(即读取字符并删除它),但是不把它存放在字符数组中,而三个参数的get函数不把分隔符放在数组中,却仍然将它保留在输入流中。 下面的程序演示了两者之间的区别: 例14.9演示get、getline的区别实例 //演示get、getline的区别 #include #include intmain() { charstr[128]; charlineStr[128]; cout<<"使用get函数,请用键盘输入下面这行字符后按回车: " <<"\nThisisALine"< cin.get(str,sizeof(str),'A'); cout<<"Firstline: "< cin.get(str,sizeof(str)); cout<<"Secondline: "< cout<<"使用getline函数,请用键盘输入下面这行字符后按回车: " <<"\nThisisALine"< cin.getline(lineStr,sizeof(lineStr),'A'); cout<<"Firstline: "< cin.getline(lineStr,sizeof(lineStr)); cout<<"Secondline: "< return0; } 演示结果如下: 使用get函数,请用键盘输入下面这行字符后按回车: ThisisALine ThisisALine Firstline: Thisis Secondline: ALine 使用getline函数,请用键盘输入下面这行字符后按回车: ThisisALine ThisisALine Firstline: Thisis Secondline: Line 可以看到使用get函数,A被保留在输入流中,成为了第二行的第一个字母,使用getline函数,A被删除掉了。 需要注意的是,使用getline时,输出的第一行字符掉到了下一行,原因在于前面第二次使用get输入时,默认分隔符为换行符,所以第一次使用getline时,实际上首先输入的是仍然保留在输入流中的换行符。 14.6数据文件的I/O操作 在C++中,对于文件的输入/输出,可以使用流类ifstream(从文件输入)、ofstream(向文件输出)和fstream(从文件输入/输出。 get()和put()只能进行单个字符的读写。 Read()和write()则能够实现成组读写。 ●write函数 原型: istream&write(constunsignedchar*ch_buffer,intnumber_bytes); 功能: 缓冲ch_buffer中写number_bytes个字节到输出流文件中。 ●read函数 原型: istream&read(unsignedchar*ch_buffer,intnumber_bytes); 功能: 从输入流文件中读number_bytes个字节到缓冲ch_buffer中。 程序举例: #include #include #include structst{ charnum[10]; charname[30]; charaddr[40]; }; intmain() { staticstructstobj; //使用ofstream类的构造函数打开文件 ofstreamoutGradeFile; outGradeFile.open("C: \\grade2.dat",ios: : out); if(! outGradeFile){ cerr<<"文件不能被打开! "< exit (1);//函数原形定义在stdlib.h中 } cout<<"? "; while(cin>>obj.num>>obj.name>>obj.addr){ outGradeFile.write((char*)&obj,sizeof(structst));
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第14章 输入与输出流类库 14 输入 输出 流类库
![提示](https://static.bdocx.com/images/bang_tan.gif)