




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第九章流类库与输入/输出福州大学吴小竹面向对象程序设计2本章主要内容I/O流的概念输出流输入流输入/输出流3I/O流的概念当程序与外界环境进行信息交换时,存在着两个对象,一个是程序中的对象,另一个是文件对象。流是一种抽象,它负责在数据的生产者和数据的消费者之间建立联系,并管理数据的流动。程序建立一个流对象,并指定这个流对象与某个文件对象建立连接,程序操作流对象,流对象通过文件系统对所连接的文件对象产生作用。读操作在流数据抽象中被称为(从流中)提取,写操作被称为(向流中)插入。4C++的基本流类体系整个流类体系是一个派生类体系。按ANSIC++标准,类ios是抽象类,它的析构函数是虚函数,它的构造函数为保护的,作为所有基本流类的虚基类。iosstreambufistreamostreamistream_withassigniostreamostream_withassigniostream_withassign指针5C++的基本流类体系streambuf是一个独立的类,只是ios有一个保护访问限制的指针指向它。streambuf的作用是管理一个流的缓冲区。ios提供了对流进行格式化输入输出和错误处理的成员函数。所有派生都是公有派生。istream类提供完成提取(输入)操作的成员函数,而ostream类提供完成插入(输出)操作的成员函数。iostream类是前两者的组合。iostreamfstreamstrstreamstdiostreamiosistreamistrstreamistream_withassignifstreamstreambuffilebufstrstreambufstdiobufiostream_initostreamofstreamostream_withassignostrstream6C++的基本流类体系
在流类库中,最重要的两部分功能为标准输入/输出(standardinput/output)和文件处理。在C++的流类库中定义了四个全局流对象:cin,cout,cerr和clog。使用这四个流对象,可以完成人机交互的功能。cin称标准输入流(对象),以键盘为其对应的标准设备。cout称标准输出流(对象),以显示器为标准设备。cerr和clog称为标准错误输出流,标准错误输出设备也是显示器。其中cin、cout和clog是带缓冲区的,缓冲区由streambuf类对象来管理。而cerr为非缓冲区流,一旦错误发生立即显示。要使用这四个功能,必须包含<iostream.h>文件。
提取运算符“>>”(stream_extractionoperator)和插入运算符“<<”(stream_insertionoperator),执行输入/输出操作。“提取”的含义是指输入操作,可看作从流中提取一个字符序列,而“插入”的含义是指输出操作,可看作向流中插入一个字符序列。7控制输出格式C++在类ios中提供格式化输入输出。这些格式是对所有文本方式的输入输出流均适用。格式控制符定义为公有的无名的枚举类型:enum{skipws=0x0001 //跳过输入中的空白字符
left=0x0002 , //输出左对齐
right=0x0004, //输出右对齐
internal=0x0008, //在输出符号或数制字符后填充
dec=0x0010, //在输入输出时将数据按十进制处理
oct=0x0020, //在输入输出时将数据按八进制处理
hex=0x0040, //在输入输出时将数据按十六进制处理
showbase=0x0080, //在输出时带有表示数制基的字符
showpoint=0x0100 , //输出符点数时,必定带小数点
uppercase=0x0200 , //输出十六进制,用大写
showpos=0x0400, //输出正数时,加”+”号
scientific=0x0800, //科学数方式输出浮点数
fixed=0x1000, //定点数方式输出实数
unitbuf=0x2000, //插入后,立即刷新流
stdio=0x4000} //插入后,立即刷新stdout和stderr8控制输出格式该枚举量说明中每一个枚举量实际对应两字节数据(16位)中的一个位,所以可以同时采用几个格式控制,只要把对应位置1即可,这样既方便又节约内存。取多种控制时,用或“|”运算符来合成,合成为一个长整型数,在ios中为:protected: longx_flags;访问x_flags的重载函数定义如下:inlinelongios::flags()const{returnx_flags;}//返回当前标志字inlinelongios::flags(long_l){//参数作为新的标志字,并返回原标志字
long_l0;_l0=x_flags;
x_flags=_l;return_l0;}inlinelongios::setf(long_l){//增加控制(多项)long_l0;_l0=x_flags;x_flags|=_l;return_l0;}//增加控制(多项)inlinelongios::unsetf(long_l){//清除指定位上的控制
long_l0;_l0=x_flags;x_flags&=(~_l);return_l0;}9控制输出格式类ios中还设置了三个输入输出流格式控制标志:protected:intx_precision;//标志浮点数精度,缺省为6位
intx_width;//输出域宽,缺省域宽为0,
//重设域宽只对其后第一输出项有效,如域宽不足,则不受限制
charx_fill;//标志域宽有富余时填入的字符相关接口函数为:inlineintios::width()const{returnx_width;}//返回当前域宽inlineintios::width(int_i){//把参数作为新的域宽,返回原域宽
int_i0;_i0=(int)x_width;x_width=_i;return_i0;}inlinecharios::fill()const{returnx_fill;}//返回当前填充字符inlinecharios::fill(char_c){//参数作为新填充字符,返回原填充字符
char_c0;_c0=x_fill;x_fill=_c;return_c0;}inlineintios::precision(inti){//参数作为新填充字符,返回原填充字符
int_i0;_i0=(int)x_presion;x_presion=_i;return_i0;}inlineintios::precision()const{returnx_presion;}//返回当前精度10例:voidmain(void){intinum=255;cout<<”十进制方式”<<inum<<’\t’;cout.flags(ios::oct|ios::showbase);
//八进制带数制基数输出是前面加0,参数等效0x00a0cout<<”八进制方式”<<inum<<’\t’;cout.flags(ios::hex|ios:showbase);
//等效0x0040,因是或关系,仍带基数输出,格式为0x...cout<<”十六进制方式”<<inum<<endl;}程序输出:十进制方式255八进制方式0377十六进制方式0xff11控制输出格式例9-1使用width控制输出宽度#include<iostream>usingnamesoacestd;intmain(){doublevalues[]={1.23,35.36,653.7,4358.24};for(inti=0;i<4;i++){cout.width(10);cout<<values[i]<<'\n';}}输出流输出结果:1.2335.36653.74358.2412例:使用*填充#include<iostream>usingnamespacestd;intmain(){doublevalues[]={1.23,35.36,653.7,4358.24};for(inti=0;i<4;i++){cout.width(10);
cout.fill('*');cout<<values[i]<<'\n';}}输出流输出结果:******1.23*****35.36*****653.7***4358.2413例9-2使用setw指定宽度#include<iostream>#include<iomanip>usingnamespacestd;intmain(){doublevalues[]={1.23,35.36,653.7,4358.24};char*names[]={"Zoot","Jimmy","Al","Stan"};for(inti=0;i<4;i++)cout<<setw(6)<<names[i]<<setw(10)<<values[i]<<endl;}输出流输出结果:
Zoot1.23Jimmy35.36Al653.7Stan4358.2414例9-3设置对齐方式#include<iostream>#include<iomanip>usingnamespacestd;intmain(){doublevalues[]={1.23,35.36,653.7,4358.24};char*names[]={"Zoot","Jimmy","Al","Stan"};for(inti=0;i<4;i++)cout<<setiosflags(ios::left)<<setw(6)<<names[i]<<resetiosflags(ios::left)<<setw(10)<<values[i]<<endl;}输出流输出结果:Zoot1.23Jimmy35.36Al653.7Stan4358.2415例9-4控制输出精度#include<iostream>#include<iomanip>usingnamespacestd;intmain(){doublevalues[]={1.23,35.36,653.7,4358.24};char*names[]={"Zoot","Jimmy","Al","Stan"};cout<<setiosflags(ios::scientific);for(inti=0;i<4;i++)cout<<setiosflags(ios::left)<<setw(6)<<names[i]<<resetiosflags(ios::left)<<setw(10)<<setprecision(1)<<values[i]<<endl;}输出流输出结果:Zoot1Jimmy4e+001Al7e+002Stan4e+00316
标准设备的输入/输出标准设备输入是最不安全的,注意以下几点,可以避免错误。1.cin为缓冲流。键盘输入的数据保存在缓冲区中,当要提取时,是从缓冲区中拿。如果一次输入过多,会留在那儿慢慢用,如果输入错了,必须在回车之前修改,如果回车键按下就无法挽回了。只有把输入缓冲区中的数据取完后,才要求输入新的数据。不可能用刷新来清除缓冲区,所以不能输错,也不能多输!2.输入的数据类型必须与要提取的数据类型一致,否则出错。出错只是在流的状态字state(枚举类型io_state)中对应位置位(置1),程序继续。所以要提高健壮性,就必须在编程中加入对状态字state的判断。3.空格和回车都可以作为数据之间的分格符,所以多个数据可以在一行输入,也可以分行输入。但如果是字符型和字符串,则空格(ASCII码为32)无法用cin输入,字符串中也不能有空格。回车符也无法读入。状态字state为整型,其的各位在ios中说明:
enumios_state{goodbit=0x00, //流正常
eofbit=0x01,
//输入流结束,忽略后继提取操作;或文件结束,已无数据可取
failbit=0x02, //最近的I/O操作失败,流可恢复
badbit=0x04, //最近的I/O操作非法,流可恢复
hardfail=0x08}//I/O出现致命错误,流不可恢复,VC++不支持
读取状态的有关操作如下:inlineintios::rdstate()const{returnstate;}//读取状态字inlineintios::bad(){returnstate&badbit;}//返回非法操作位inlinevoidios::clear(int_i){lock();state=_i;unlock();}
//人工设置状态,可用来清状态inlineintios::eof()const{returnstate&eofbit;}//返回流结束位inlineintios::fail()const{returnstate&(badbit|failbit);}
//返回操作非法和操作失败这两位inlineintios:operator!()const{returnstate&(badbit|failbit);}
//可用操作符!()代替fail()inlineintios::good()const{returnstate==0;}//正常返回1
18标准设备的输入/输出【例】提高输入的健壮性。输入时需要故意输错,以测试健壮性。voidmain(){charstr[256];inti;cout<<"请输入整数:"<<endl;//强制清空缓冲区,保证输出
cin>>i;//可输入非数字字符,下次再输入若干字符加数字串等进行检测
while(cin.fail()){cout<<cin.rdstate()<<endl;//输出状态字
cin.clear(0);//清状态字
cin.getline(str,255);//读空缓冲区
cout<<"输入错误,请重新输入整数"<<endl;cin>>i;}cin.getline(str,256);//读空缓冲区
cout<<"请输入字符串"<<endl;cin.getline(str,255);cout<<"输入整数为:"<<i<<endl;cout<<"输入字符串为:"<<str<<endl;}19输入输出流中的成员函数输入流成员函数声明:istream&istream::get(char&);//提取一个字符,放在字符型变量中istream&istream::get(char*,int,char=’\n’);
//提取字符串,到串结束符或指定长度为止istream&istream::getline(char*,int,char=’\n’);//同上,包括分隔符标准设备的输入/输出20用下面的函数返回最后一次提取的字符数量,包括回车intistream::gcount()const{returnx_gcoutnt;}还有一个成员函数可用来读空(指定一个大的数量)缓冲区:istream&istream::ignore(int=1,int=EOF);第一个参数为要提取的字符数量,缺省为1;第二个参数表示遇到该字符则结束,包括该结束字符,但对所提取的字符不保存不处理,作用是空读。第二个参数的缺省值EOF为文件结束标志。标准设备的输入/输出21【例】ignore()和gcount()函数使用。voidmain(){charstr[255];inti,n;cout<<"输入字符"<<endl;i=cin.get();//请输入^Z,一旦输入^Z全部结束,不能输入其它字符
cout<<endl;n=cin.rdstate();//读取状态字
cout<<"状态字为:"<<n<<endl;//状态字为1,流结束标准设备的输入/输出
cout<<"当输入字符时,取得的是:"<<i<<endl;//输入^Z时,返回EOF,即-1if(n==0)cin.ignore(255,'\n');//清除多余的字符和回车符
cin.clear(0);//A使流恢复正常
cout<<"输入字符串1:"<<endl;cin.getline(str,255);cout<<endl;cout<<"状态字为:"<<cin.rdstate()<<endl;i=cin.gcount();cout<<"字符串为:"<<str<<'\t'<<"读入字符数为:"<<i<<'\t';cout<<"串长为:"<<strlen(str)<<endl;cin.clear(0);//Acout<<"输入字符串2:"<<endl;cin.getline(str,255);cout<<endl;cout<<"状态字为:"<<cin.rdstate()<<endl;i=cin.gcount();cout<<"字符串为:"<<str<<'\t'<<"读入字符数为:"<<i<<'\t';cout<<"串长为:"<<strlen(str)<<endl;}注意,若无两个A行,输入^Z时,不再理会余下的所有输入。输出流成员函数声明:ostream&ostream::put(char);//输出参数字符ostream&ostream::flush();//刷新一个输出流,用于cout和clogC++允许用户重载插入和提取运算符“<<”和“>>”,以便用户利用标准的输入/输出流来输入/输出自定义的数据类型,实现对象的输入输出。重载必须保留原来的使用特性。重载可在用户定义类中,将重载的运算符的函数说明为该类的友元函数:friendistream&operator>>(istream&,className&);friendostream&operator<<(ostream&,className&);函数的返回值为对输入或输出流的引用,这是为了保证在cin和cout中可以连续使用“>>”或“<<”运算符,与所有“>>”和“<<”重载函数一致。第一个参数也是输入或输出流的应用,作为“>>”或“<<”的左操作数;第二个参数为用户定义类的引用,作为右操作数。【例】用户定义的复数类型Complex的输入与输出。classComplex{doubleReal,Image;public:Complex(doubler=0.0,doublei=0.0):Real(r),Image(i){};friendostream&operator<<(ostream&s,constComplex&z){returns<<'('<<z.Real<<','<<z.Image<<')';}friendistream&operator>>(istream&s,Complex&a){doublere=0,im=0;S>>re;s>>im; a=Complex(re,im);returns;}};25标准设备的输入/输出【例】通常用输出数组名得到的是数组地址,但字符型数组(串)不同,输出的是数组内容。本例将字符指针强制转换为泛型指针输出字符串地址。#include<iostream.h>voidmain(){char*string1="欢迎学习C++程序设计课程!";cout<<"串值是:"<<string1<<"\n串地址是:"<<(void*)string1<<endl;}26文件的输入与输出
本节中文件指的是磁盘文件。C++根据文件(file)内容的数据格式,可分为两类:二进制文件和文本文件。文本文件由字符序列组成,也称ASCII码文件,在文本文件中存取的最小信息单位为字符(character),而二进制文件中存取的最小信息单位为字节(Byte)。27文件的打开与关闭文件的使用步骤如下:1.说明一个文件流对象,这又被称为内部文件:
ifstreamifile;//只输入用
ofstreamofile;//只输出用
fstreamiofile;//既输入又输出用
2.使用文件流对象的成员函数打开一个磁盘文件。这样在文件流对象和磁盘文件名之间建立联系。文件流中说明了三个打开文件的成员函数。voidifstream::open(constchar*,int=ios::in,int=filebuf::openprot);voidofstream::open(constchar*,int=ios::out,int=filebuf::opernprot);voidfstream::open(constchar*,int,int=filebuf::openprot);第一个参数为要打开的磁盘文件名。第二个参数为打开方式,有输入(in),输出(out)等,打开方式在ios基类中定义为枚举类型。第三个参数为指定打开文件的保护方式,一般取缺省。所以第二步可如下进行:iofile.open(“myfile.txt”,ios::in|ios::out);28文件的打开与关闭三个文件流类都重载了一个带缺省参数的构造函数,功能与open函数一样:ifstream::ifstream(constchar*,int=ios::in,int=filebuf::openprot);ofstream::ofstream(constchar*,int=ios::out,int=filebuf::openprot);fstream::fstream(constchar*,int,int=filebuf::operprot);所以1,2两步可合成:fstreamiofile(”myfile.txt”,ios::in|ios::out);打开文件也应该判断是否成功,若成功,文件流对象值为非零值,不成功为0(NULL)。因此打开一个文件完整的程序为:fstreamiofile(”myfile.txt”,ios::in|ios::out);if(!iofile){cout<<”不能打开文件:”<<”myfile,txt”<<endl;exit(1);}29文件的打开与关闭3.使用提取和插入运算符对文件进行读写操作,或使用成员函数进行读写,这在下一节中讨论。4.关闭文件。三个文件流类各有一个关闭文件的成员函数
voidifstream::close();voidofstream::close();voidfstream::close();使用很方便,如:iofile.close();关闭文件时,系统收回与该文件相关的内存空间,可供再分配,把磁盘文件名与文件流对象之间的关联断开,可防止误操作修改了磁盘文件。如又要对文件操作必须重新打开。
关闭文件并没有取消文件流对象,该文件流对象又可与其他磁盘文件建立联系。文件流对象在程序结束时,或它的生命期结束时,由析构函数撤消。它同时释放内部分配的预留缓冲区。
30文件的打开与关闭文件打开方式是在ios类中定义的,公有枚举成员:enum
open_mode{ in=0x01,//打开文件用于输入操作(从文件读取),文件指针在文件头out=0x02,/*打开文件用于写入文件。如文件不存在,则建立,但指定目录必须存在,否则建立文件失败。如文件存在,未同时设
app,ate,in则文件清空*/ate=0x04,
//打开文件用于输入/输出,文件指针在文件尾,但新数据可写到任何位置app=0x08,//打开文件用于输出,但从尾部添加,新数据只能添加在尾部trunce=0x10,//打开文件,并清空它,以建立新文件nocreate=0x20,//如文件存在则打开,不存在并不创建新文件noreplace=0x40,
//如文件不存在则创建,如文件存在则只能设为ate及app方式binary=0x80};//以二进制方式打开文件使用方法与格式控制符相同31文件的打开与关闭这里输入指以文件为信息的源,由文件流进入系统(系统为操作主体),相当于提取(>>),是读操作(系统读)。而输出指以文件为信息的汇,信息由系统插入文件流到达磁盘文件,是写操作(系统写)。除ate和app方式外,其他方式打开文件,文件定位指针均置于文件的起始位置。具体选择哪种方式取决于文件的读写要求。如文件不存在,有些方式可建立文件,但指定目录必须存在,否则建立文件失败。32文本文件的读写
这里讨论文本文件的顺序读写。顺序读写可用C++的提取运算符(>>)和插入运算符(<<)进行。【例】复制文件。voidmain(){ifstreamsfile("d:\\Ex9_6\\Ex9_6.cpp");ofstreamdfile("e:\\Ex9_6.cpp");
//只能创建文件,不能建立子目录,如路径不存在则失败
charch;if(!sfile){cout<<"不能打开源文件:"<<"d:\\Ex9_6\\Ex9_6.cpp"<<endl;exit(1); }if(!dfile){cout<<"不能打开目标文件:"<<"e:\\Ex9_6.cpp"<<endl;exit(1);}sfile.unsetf(ios::skipws);
//关键!把跳过空白控制位置0,即不跳过空白,否则空白全部未拷贝
while(sfile>>ch)dfile<<ch;sfile.close();//如没有这两个关闭函数,析构函数也可关闭
dfile.close();}33文本文件的读写该程序中,首先必须设置关闭跳过空白,因为提取(“>>”)运算符在缺省情况下是跳过空白(包括空格,制表,backspace和回车等)的,这样拷贝的文件会缺少一些字符。第二,该程序能确定文件是否拷贝结束。流类成员函数和运算符全是返回本类型的引用,这里就是流文件对象自身,当文件结束时,返回NULL,这时不再拷贝,退出循环。第三,拷贝是按字节进行的,效率很低,按字节传递开销极大,但该程序能正确拷贝任意类型的文件,不仅是文本文件(看作按字符),二进制文件(看作按字节)也一样可正确完成。如果是文本文件,我们可以按行进行拷贝。第四,!sfile中的!是重载的运算符,在状态函数中重载,当该操作出现不正常状态,返回true。【例】按行复制文本文件。voidmain(){charfilename[256],buf[100];fstreamsfile,dfile;cout<<"输入源文件路径名:"<<endl;cin>>filename;
//对路径各方面而言空格是无关紧要的,否则要用getline()等成员函数
sfile.open(filename,ios::);//打开一个已存在的文件
while(!sfile){cout<<"源文件找不到,请重新输入路径名:"<<endl;cin>>filename;sfile.open(filename,ios::in);}cout<<"输入目标文件路径名:"<<endl;cin>>filename;//只能创建文件,不能建立子目录,如路径不存在则失败
dfile.open(filename,ios::out);if(!dfile){cout<<"目标文件创建失败"<<endl;exit(1);}while(sfile.getline(buf,100)){//按行拷贝A行
if(sfile.gcount()<100)dfile<<buf<<‘\n’;//因回车符未送到B行
elsedfile<<buf;}
//本行大于99个字符,还未读到回车换行符,所以不加'\n'sfile.close();dfile.close();}35文本文件的读写A行中sfile.getline(buf,100)从源文件读一行字符,或读99个字符,效率大大提高。B行中,因从源文件读字符是遇到行结束(回车换行)符停止的,所以文件中应有一个回车换行符;但getline()回车换行符并不放在buf中,因此要加一个回车换行符,但此程序只能用于文本文件。【例】文本式数据文件的创建与读取数据。本例演示的是典型的C++数据存入文件和由文件获得数据的方法,按面向对象的说法为把对象存入文件和由文件重构对象。本例对提取和插入运算符进行了重载,只用一个“>>”完成重构对象,而只用一个“<<”完成对象存入文件。
classinventory{charDescription[20],No[10];intQuantity;doubleCost,Retail;public:inventory(char*="#",char*="0",int=0,double=0,double=0);voiddisplay(ostream&dist);friendostream&operator<<(ostream&dist,inventory&iv);friendistream&operator>>(istream&sour,inventory&iv);};inventory::inventory(char*des,char*no,intquan,doublecost,doubleret){strcpy(Description,des);strcpy(No,no);Quantity=quan;Cost=cost;Retail=ret;}voidinventory::display(ostream&dist){dist.setf(ios::left);dist<<setw(20)<<Description<<setw(10)<<No;cout.unsetf(ios::left);//要改为右对齐,先清左对齐
dist.setf(ios::right);dist<<setw(10)<<Quantity<<setw(10)<<Cost<<setw(10)<<Retail<<endl;}//显示时是把浮点数转为数字串后显示,函数体内<<功能不变ostream&operator<<(ostream&dist,inventory&iv){iv.display(dist);returndist;}//把数转为数字串后写入Istream&operator>>(istream&sour,inventory&iv){sour>>iv.Description>>iv.No>>iv.Quantity>>iv.Cost>>iv.Retail;returnsour;}
//从文件读出是把数字串转为数读出,但函数体内“>>”功能不变voidmain(){inventorycar1("夏利2000","805637928",156,80000,105000),car2;inventorymotor1("金城125","93612575",302,10000,13000),motor2;ofstreamdistfile("d:\\Ex9_9.data");distfile<<car1<<motor1;//注意ofstream是ostream的派生类,写入文件
distfile.close();//关闭文件
car1.display(cout);motor1.display(cout);car2.display(cout);motor2.display(cout);ifstreamsourfile("d:\\Ex9_9.data");
sourfile>>car2>>motor2;//文件数据顺序写入car2和motor2sourfile.close();car2.display(cout);motor2.display(cout);}按C++的常规,资源获取是由构造函数实现,而资源释放是由析构函数完成。所以与内存动态分配一样,由文件重构对象放在构造函数中,把对象存入文件则放在析构函数中。38二进制文件的读写C++提供了对二进制文件进行读写的成员函数:istream&istream::read(char*,int);//从二进制流提取//第一个参数指定存放有效输入的变量地址,第二个参数指定提取的字节数,//函数从输入流提供指定数量的字节送到指定地址开始的单元ostream&ostream::write(constchar*,int);//向二进制流插入//第一个参数指定输出对象的内存地址,第二个参数指定插入的字节数,//函数从该地址开始将指定数量的字节插入输入输出流读函数并不能知道文件是否结束,可用状态函数intios::eof()来判断文件是否结束。必须指出系统是根据当前操作的实际情况设置状态位,如需根据状态位来判断下一步的操作,必须在一次操作后立即去调取状态位,以判断本次操作是否有效。39二进制文件的读写【例】创建二进制数据文件,以及数据文件的读取。这两项操作设计为成员函数。inventory::Bdatatofile(ofstream&dist){ dist.write(Description,20); dist.write(No,10); dist.write((char*)&Quantity,sizeof(int)); dist.write((char*)&Cost,sizeof(double)); dist.write((char*)&Retail,sizeof(double));}inventory::Bdatafromfile(ifstream&sour){ sour.read(Description,20); sour.read(No,10); sour.read((char*)&Quantity,sizeof(int)); sour.read((char*)&Cost,sizeof(double)); sour.read((char*)&Retail,sizeof(double));}//由此可见读和写是完全对称的过程,次序决不能错ofstreamddatafile("d:\\Ex9_10.data",ios::out|ios::binary);car1.Bdatatofile(ddatafile);motor1.Bdatatofile(ddatafile);//ddatafile.close();ifstreamsdatafile("d:\\Ex9_10.data",ios::in|ios::binary);//重新打开文件,从头读取数据car2.Bdatafromfile(sdatafile);//从文件读取数据拷贝到对象car2if(sdatafile.eof()==0)cout<<"读文件成功"<<endl;使用二进制文件,可以控制字节长度,读写数据时不会出现二义性,可靠性高。同时不知格式是无法读取的,保密性好。文件结束后,系统不会再读,但程序不会自动停下来,所以要判断文件中是否已没有数据。如写完数据后没有关闭文件,直接开始读,则必须把文件定位指针移到文件头。如关闭文件后重新打开,文件定位指针就在文件头。41文件的随机访问
C++把每一个文件都看成一个有序的字节流,见图,每一个文件或者以文件结束符(endoffilemarker)结束,或者在特定的字节号处结束。012436578…n-1…文件结束符图C++把文件看作有序的n个字节的流当打开一个文件时,该文件就和某个流关联起来了。对文件进行读写实际上受到一个文件定位指针(filepositionpointer)的控制,输入流的指针也称为读指针,每一次提取操作将从读指针当前所指位置开始,每次提取操作自动将读指针向文件尾移动。输出流指针也称写指针,每一次插入操作将从写指针当前位置开始,每次插入操作自动将写指针向文件尾移动。42文件的随机访问
在C++中可以由程序移动文件指针,从而实现文件的随机访问,即可读写流中任意一段内容。一般文本文件很难准确定位,所以随机访问多用于二进制文件。在ios类中说明了一个公有枚举类型:enumseek_dir{ beg=0,//文件开头
cur=1,//文件指针的当前位置
end=2//文件结尾};istream类中提供了如下三个成员函数:istream&istream::seekg(streampos);//指针直接定位istream&istream::seekg(streamoff,ios::seek_dir);//指针相对定位longistream::tel
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 电动汽车电池热管理关键技术突破与创新应用分析报告
- 2024年“消费者心理学及行为学”知识考试题库与答案
- 工业互联网平台边缘计算硬件架构优化与工业设备远程控制报告
- 2025年土壤污染修复技术环保法规政策分析报告
- 2023沪教牛津版七年级下学期英语练习-Unit 4素养综合检测
- 2023高中数学必考知识点复习梳理
- 二零二五年度房改房二手房买卖保险附加服务合同
- 二零二五年度房屋拆除与临时安置协议书
- 2025版节能建筑改造工程设计与施工监理合同标的节能管理
- 二零二五年度农村住房抵押贷款合同范本
- 浙江省2023-2024学年七年级下学期英语期中试卷(含答案)
- 越南音响行业分析
- 电力维保服务方案
- 少年中国说英文版
- 少儿口才训练材料(30篇)
- 食堂消毒间管理制度
- 门式钢管脚手架验收记录表
- 体育旅游课件第二章体育旅游资源
- 水务集团供水有限公司员工行为准则
- PS6000+自动化系统用户操作手册
- 海康威视枪机摄像机检测报告
评论
0/150
提交评论