第14章输入与输出流类库_第1页
第14章输入与输出流类库_第2页
第14章输入与输出流类库_第3页
第14章输入与输出流类库_第4页
第14章输入与输出流类库_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第14章 输入与输出流类库C+的I/O流类,是目前最常用的I/O系统。本章介绍C+输入与输出流类库。通过本章的学习,读者可以了解怎样使用C+面向对象的输入/输出流,能够格式化输入和输出,了解I/O流类的层次结构,了解怎样输入/输出用户自定义类型的对象,能够建立用户自定义的流操作符,能够确定输入/输出操作的成功与失败,能够把输出流连到输入流上。14.1 I/O流类的结构(略)14.2 文件流类C+语言把每个文件都看成一个有序的字节流。每个文件或者以文件结束符结束,或者在特定的字节号处结束(该字节号通常记录在由系统维护和管理的数据结构中)。当打开一个文件时,该文件就和某个流关联起来。系统自动生成c

2、in、cout、cerr、clog对象,流使用这些对象所关联的特定文件或输入/输出设备和程序之间建立通信通道。要在C+中进行文件处理,就要包含头文件<iostream.h>和<fstream.h>。<fstream.h>头文件包括流类 ifstream(从文件输入)、ofstream(向文件输出)和fstream(从文件输入/输出)的定义。生成这些流类的对象即可打开文件。这些流类分别从istream、ostream和iostream类派生。其层次结构如图14.2。图14.2 文件流类的继承关系在C+中,要定义一个文件流类对象,必须规定文件名和打开方式。类of

3、stream用于执行文件输出,该类有几个构造函数,其中最有用的是:ofstream:ofstream(char* pFileName, /指向要打开的文件名字符串 int nMode = ios:out, /打开方式 int nProt = filebuf:openprot); /文件保护方式nMode参数是打开方式,它的含义见表14.1 表14.1 文件打开选择项标志含义ios:app将所有输出写入文件尾ios:ate打开文件以便输出,并移到文件末尾(通常用于添加数据),数据可以写入文件中的任何地方ios:in打开文件以便写入(ifstream默认)ios:out打开文件以便输出(ofstr

4、eam默认)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+把文件看作是无结构的字节流,所以为了在文件中记录特定结构的内容,必须给文件加上记录结构。下面的程序演示了班级学生成绩表,学号作为记录关键字,文件按学号顺序建立

5、和维护。假定用户按学号顺序键入记录,程序将把键入的记录保存并写入文件。程序示例如下。例14.4 文件流操作实例/演示文件流操作#include "stdafx.h"#include<iostream.h>#include<fstream.h>#include<stdlib.h>int main()int regNumber;char name30;float grade;/使用ofstream类的构造函数打开文件ofstream outGradeFile("C:grade.dat",ios:out);/也可以先创建输出

6、流类对象,再用open操作打开文件/ofstream outGradeFile;/outGradeFile.open("C:grade.dat",ios:out);if(!outGradeFile)cerr<<"文件不能被打开!"<<endl;exit(1);/函数原形定义在stdlib.h中cout<<"请输入学号,姓名,和成绩,n"<<"按输入文件结束符结束。n? " while(cin>>regNumber>>name>>gr

7、ade)outGradeFile<<regNumber<<" "<<name <<" "<<grade<<'n'cout<<"? "outGradeFile.close();ifstream inGradeFile("C:grade.dat",ios:in);/也可以先创建输入流类对象,再用open操作打开文件/ifstream inGradeFile;/inGradeFile.open("C:grade.

8、dat",ios:in);cout<<"? "while(inGradeFile>>regNumber>>name>>grade)cout<<regNumber<<" "<<name <<" "<<grade<<'n'cout<<"? "inGradeFile.close();return 0; /ofstream的析构函数将关闭文件程序运行结果如下:请输入学

9、号,姓名,和成绩,按输入文件结束符结束。 ?123 aaa 78 ?234 bbb 89 ?345 ccc 69 ?Z ?123 aaa 78 ?234 bbb 89 ?345 ccc 69上例中,对于文件名要说明其路径,斜杠要双写,因为编译器理解下的斜杠是字符转换符。这和包含头文件时的路径不一样,因为包含头文件是由编译预器处理的。文件打开时,对于使用ofstream类构造对象时,其打开方式默认为ios:out|ios:trunc,即该文件每次打开,如果原先存在,则都会先被清空内容,否则就新建。如果要打开二进制文件,写方式,输出到文件尾,可以如下操作:ofstream bfile(“binfi

10、le”,ios:binary|ios:ate);也可以生成oftream对象而不打开特定文件,而在后面再将文件与对象相连接。可以如下操作:ofstream outFile;outFile.open(“abc.dat”,ios:out);如果需要打开一个输入文件,从文件中读取数据可以如下操作:ifstream myinf(“C:grade.dat”,ios:nocreate);if(myinf.fail()cerr<<”打开文件出错!n”;return;myinf>>regNumber>>name>>grade;对于打开文件是否操作成功,可以使用重

11、载的ios运算符成员函数!操作符确定打开是否成功,如果打开操作的流将failbit或badbit置位,则条件(!outGradeFile)返回非0值(true);也可以通过判断fail()成员函数来确定打开文件是否出错。如果打开文件同时用于输入和输出,则可以如下操作:fstream myinout(“abc.dat”,ios:in|ios:out);用fstream打开的文件,打开方式不能默认。14.3 串流类(不讲)ostrstream、istrstream、strstream是串流类,在strstrea.h中定义。其中,strstream类是从ostrstream和istrstream类多

12、重继承而来的子类。要定义一个串流类对象,须提供字符数组和数组大小。类istrstream用于串流输入,该类有几个构造函数,其中最有用的是:istrstream:istrstream(const char* pch);istrstream:istrstream(const char* pch,int nLength);第一个参数指出字符串数组,第二个参数说明数组大小。当size为0时,表示把istrstream类对象连接到由pch指向的以空字符结束的字符串。类ostrstream用于执行串流输出,该类也有几个构造函数,其中最有用的是:ostrstream:ostrstream(char* pch

13、,int nLength,int nMode=ios:out);第一个参数指出字符串数组,第二个参数说明数组大小,第三个参数指出打开方式。下面的实例演示了如何使用串流输入输出功能。例14.5 串流输入输出功能实例/演示串流输入输出功能#include<iostream.h>#include<strstrea.h>#include<string.h>char* parseString(char* pch)int number;float balance; /计算需要构造的串流类的长度/strlen返回字符串长度,其定义包含在string.h中int nLeng

14、th=strlen("帐号:") +strlen(" 收支:")+strlen(pch); istrstream inp(pch,0); /ios:in方式,读到null结束 inp>>number>>balance; /从串流中读入一个整数和浮点数char *pBuffer=new charnLength;ostrstream outp(pBuffer,nLength);/ios:out方式,字串长度为计算出的nLength, /刚好满足输出到pBuffer中的长度要求outp<<"帐号:"<

15、;<number<<" 收支:"<<balance; /写入pBuffer中 /注意该处如果写入超出pBuffer空间长度的字符, /超出部分将不会被写入return pBuffer;int main()char *pch="1001 125.45"char *pBuf=parseString(pch);cout<<pBuf<<endl; delete pBuf;return 0;演示结果如下:帐号:1001 收支:125.45在函数parseString()中,先定义了一个输入串流对象inp,将输入

16、设备pch中的字符输入到了一个整数和一个浮点数中,然后,定义了一个输出串流对象outp,将提示信息和这两个变量输出到outp连接的输出设备(实际为一字符串空间)pbuffer中。注意语句:outp<<"帐号:"<<number<<" 收支:"<<balance;它同时也将提示信息“帐号:”、“收支:”也写入到了输出设备pbuffer中。14.4 格式控制(浏览)C+提供了大量用于执行格式化输入/输出的流格式控制以及流对象成员函数。比如:设置域宽、设置精度、设置和清除格式化标志、设置域填充符、刷新流、在输出流

17、中插入换行符并刷新该流、在输出流中插入空字符、跳过输入流中的空白字符等等。控制符是在头文件iomanip.h中定义的对象,可以将它们直接插入流中,来控制流输入/输出的格式。使用成员函数控制,则需要在格式化输出之前调用相关格式设置成员函数。14.4.1整数流的基数控制整数通常被解释为十进制(基数为10)整数。可以通过在流中插入控制符而改变流中整数的基数。插入控制符hex可设置成十六进制基数;插入控制符oct可设置成八进制基数、插入控制符dec可恢复十进制基数。同样可以使用成员函数flags来设置整数流的基数。下面的程序演示了这些控制符和成员函数的用法。例14.6 整数流格式控制实例/演示整数流格

18、式控制#include<iostream.h>#include<iomanip.h>int main()int n;cout<<"输入一个十进制整数:"cin>>n;cout<<n<<"的十六进制为: "<<hex<<n<<'n'<<dec<<n<<"的八进制为: "<<oct<<n<<'n'cout.flags(10);co

19、ut<<"恢复十进制为:"<<n<<endl;return 0;演示结果如下:输入一个十进制整数:1515的十六进制为: f15的八进制为: 17恢复十进制为:1514.4.2设置浮点数精度控制浮点流的精度,可以使用控制符setprecision或成员函数precision来格式化小数点后面的位数。语句:cout<<setprecision(4)<<fValue;和语句:cout.precision(4);cout<<fValue;起到了同样的效果,都将浮点型数据fValue按精确到小数点后面4位数输出

20、。14.4.3 设置域宽成员函数ios:width设置当前的域宽(即输入输出的字符数)并返回以前设置的域宽。如果显示数据所需的宽度比设置的域宽小,空位用填充字符填充。如果显示数据所需的宽度比设置的域宽大,显示数据并不会被截断,而是输出所有位,但可能会出现乱码。控制符setw也可以用来设置域宽。它们的用法如下:cout.width(8);cout<<10;上面的语句将在输出10之前输出6个空格(默认填充符)。cout<<setw(8)<<10;这条语句可以起到同样的效果。需要注意的是setw(n)或width(n)在下一个域输出后,域宽回到原先的默认值。set

21、w()的默认域宽为0,意思是按输出对象的表示宽度输出。下面的语句中,20将紧挨着10输出。cout<<setw(8)<<10<<20;14.4.4 设置填充符可以使用成员函数fill或控制符setfill来改变所要填充的字符。cout.fill(*);cout<<setw(8)<<10;输出结果为:*10由于输出域宽为8,所以在10前面填充了6个*。下面的语句将起到同样的效果。cout<<setfill(*)<<set(8)<<10;14.4.5 用户自定义流格式控制符C+提供了非常多的流格式控制符

22、和成员函数来格式化流输入/输出。上面仅介绍了常用的几种控制和成员函数的使用方法。在这里,再简单介绍一种用户自定义流控制符的方法。先看下面的程序示例:例14.7 用户自定义流格式控制符实例/演示用户自定义流格式控制符#include<iostream.h>/警告符,输出时会发出系统警告声音ostream& bell(ostream& output) return output << 'a'/回车符ostream& ret(ostream& output) return output << 'r'/

23、水平制表符,是光标移到下一个制表位ostream& tab(ostream& output) return output << 't'/换行符ostream& endLine(ostream& output) return output<<'n'<<flush;int main()cout<<"测试制表符:"<<endLine<<'a'<<tab<<'b'<<tab<

24、<'c'<<endLine<<"测试回车符和警告符:"<<endLine<<"."cout<<bell;cout<<ret<<"-"<<endLine;return 0;演示结果如下:测试制表符:a b c测试回车符和警告符:-.在上面的例子中,演示了如何建立和使用新的流控制符bell、ret、tab和endLine。需要注意的是,程序用endLine插入输出了换行符,然后输出7个省略号.,输出系统警告声,再插入ret

25、回车,再输出5个破仄号-,结果省略号被破仄号覆盖了前面部分。14.5 流类成员函数的使用在C+中,经常使用cin、cout来做输入/输出。比较常用的I/O流的成员函数有get、getline、put、eof等。Get函数原型有很多个,比较常用的函数原型有:char istream:get();istream& istream:get(char* pch, int nCount,char delim=n”);istream& get( char& rch );不带参数的get函数从指定的输入流中读取一个字符(包括空白字符),并返回该字符,当遇到输入流中的文件结束符时,返回

26、EOF。带一个字符型参数的get成员函数自动读取一个字符(包括空白字符)到字符型参数中。当遇到文件结束符时,返回0,否则返回对istream对象的引用。带三个参数的get成员函数的参数分别是接收字符的字符数组、字符数组的大小和分隔符(默认值为n)。该函数或者在读取比指定的最大字符数少一个字符后结束,或者在遇到分隔符时结束。下面的程序循环读入字符,直到用户键入一个Y字符,或遇到文件结束符(在UNIX与Macintosh上,文件结束符为<ctrl>-d,在PC与VAX上文件结束符为<ctrl>-z ):例14.8 I/O流成员函数的使用实例/演示I/O流的get、put、e

27、of成员函数的使用#include<iostream.h>#include<ctype.h>int main()char ch;while(!cin.eof()ch=cin.get();ch=toupper(ch);if(ch='Y') cout.put(ch); break; cout<<ch;return 0;上例中使用了toupper函数将键入字符全部转换成大写字母后赋值给ch,使用该函数应包含头文件ctype.h。使用带三个参数的get函数,会比较安全。例如下面这种代码:istream fin(“abc.dat”);char buf8

28、0;fin>>buf;应改成:istream fin(“abc.dat”;char buf80;fin.get(buffer,80);getline成员函数原型为:getline(char* pch, int nCount,char delim=n”);getline函数与带三个参数的get函数类似,它读取一行信息到字符数组中,然后插入一个空字符。所不同的是,getline要去除输入流中的分隔符(即读取字符并删除它),但是不把它存放在字符数组中,而三个参数的get函数不把分隔符放在数组中,却仍然将它保留在输入流中。下面的程序演示了两者之间的区别:例14.9演示get、getline

29、的区别实例/演示get、getline的区别#include<iostream.h>#include<string.h>int main()char str128;char lineStr128;cout<<"使用get函数,请用键盘输入下面这行字符后按回车:"<<"nThis is A Line"<<endl;cin.get(str,sizeof(str),'A');cout<<"First line:"<<str<<en

30、dl;cin.get(str,sizeof(str);cout<<"Second line:"<<str<<endl;cout<<"使用getline函数,请用键盘输入下面这行字符后按回车:"<<"nThis is A Line"<<endl;cin.getline(lineStr,sizeof(lineStr),'A');cout<<"First line:"<<lineStr<<endl;

31、cin.getline(lineStr,sizeof(lineStr);cout<<"Second line:"<<lineStr<<endl;return 0;演示结果如下:使用get函数,请用键盘输入下面这行字符后按回车:This is A LineThis is A LineFirst line:This isSecond line:A Line使用getline函数,请用键盘输入下面这行字符后按回车:This is A LineThis is A LineFirst line:This isSecond line: Line可以看

32、到使用get函数,A被保留在输入流中,成为了第二行的第一个字母,使用getline函数,A被删除掉了。需要注意的是,使用getline时,输出的第一行字符掉到了下一行,原因在于前面第二次使用get输入时,默认分隔符为换行符,所以第一次使用getline时,实际上首先输入的是仍然保留在输入流中的换行符。14.6 数据文件的I/O操作在C+中,对于文件的输入/输出,可以使用流类 ifstream(从文件输入)、ofstream(向文件输出)和fstream(从文件输入/输出。get()和put()只能进行单个字符的读写。Read()和write()则能够实现成组读写。l write函数原型:ist

33、ream& write(const unsigned char * ch_buffer,int number_bytes);功能:缓冲ch_buffer中写number_bytes个字节到输出流文件中。l read函数原型:istream& read(unsigned char * ch_buffer,int number_bytes);功能:从输入流文件中读number_bytes个字节到缓冲ch_buffer中。程序举例:#include<iostream.h>#include<fstream.h>#include<stdlib.h>st

34、ruct stchar num10;char name30;char addr40;int main()static struct st obj;/使用ofstream类的构造函数打开文件ofstream outGradeFile;outGradeFile.open("C:grade2.dat",ios:out);if(!outGradeFile)cerr<<"文件不能被打开!"<<endl;exit(1);/函数原形定义在stdlib.h中cout<<"? " while(cin>>o

35、bj.num>>>>obj.addr)outGradeFile.write(char *)&obj,sizeof(struct st);cout<<"? "outGradeFile.close();ifstream inGradeFile;inGradeFile.open("C:grade2.dat",ios:in);cout<<"? "/inGradeFile.seekg(0,ios:beg);while(!inGradeFile.eof()inGradeFil

36、e.read(char *)&obj,sizeof(struct st);cout<<obj.num<<<<obj.addr<<'n'cout<<"? "inGradeFile.close();return 0; /ofstream的析构函数将关闭文件程序运行结果如下:? 111 aaa vvvvvvvvvvvv? 222 bbb ddddddddddd? 333 ccc mmmmmmmmmmmmmmm? Z? 111aaavvvvvvvvvvvv? 222bbbdddddd

37、ddddd? 333cccmmmmmmmmmmmmmmm? 333cccmmmmmmmmmmmmmmm注意:输出多了一行,为什么?l 文件指针文件指针分: 读指针和写指针。l 读指针:用于读过程中定位文件中的对象。在ifstream,可以用成员函数seekg()来定位读指针。seekg函数:原型:ifstream& seekg(streamoff file_offset, seek_dir org);功能:将读指针定位在从seek_dir org开始且偏移量为file_offset处。streamoff类型在iostream.h中定义;seek_dir org的取值为:ios:beg

38、文件开始处ios:end 文件结束处ios:cur 当前位置l 写指针:用于写过程中定位文件中的对象。在ofstream,可以用成员函数seekp()来定位写指针。seekp函数:原型:ofstream& seekp(streamoff file_offset, seek_dir org);功能:将写指针定位在从seek_dir org开始且偏移量为file_offset处。streamoff类型在iostream.h中定义;seek_dir org的取值为:ios:beg 文件开始处ios:end 文件结束处ios:cur 当前位置程序举例:#include "stdafx

39、.h"#include<iostream.h>#include<fstream.h>#include<stdlib.h>struct stchar num10;char name30;char addr40;int main()static struct st obj;ifstream inGradeFile;inGradeFile.open("C:grade2.dat",ios:in);cout<<"? "inGradeFile.seekg(1*sizeof(struct st),ios:beg);while(!inGradeFile.eof()inGradeFile.read(char *)&obj,sizeof(struct st);cout<<obj.num<<<<obj.addr<<'n'cout<<&qu

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论