C++程序设计第2版习题解答_第1页
C++程序设计第2版习题解答_第2页
C++程序设计第2版习题解答_第3页
C++程序设计第2版习题解答_第4页
C++程序设计第2版习题解答_第5页
已阅读5页,还剩46页未读 继续免费阅读

下载本文档

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

文档简介

第九章流类库和输入/输出习题本概念与基础知识测试题填空题9.1.1在C++中“流”是表达(1)。从流中取得数据称为(2),用符号(3)表达;向流中添加数据称为(4),用符号(5)表达。答案:(1)数据从一个对象到另一个对象的传送(2)提取操作(3)>>(4)插入操作(5)<<9.1.2抽象类模板(1)是所有基本流类的基类,它有一个保护访问限制的指针指向类(2),其作用是管理一个流的(3)。C++流类库定义的cin,cout,cerr和clog是(4)。cin通过重载(5)执行输入,而cout,cerr和clog通过(6)执行输出。答案:(1)basic_ios(2)basic_streambuf(3)缓冲区(4)全局流对象(5)>>(stream_extractionoperator)(6)<<(stream_insertionoperator)9.1.3C++在类ios中定义了输入输出格式控制符,它是一个(1)。该类型中的每一个量相应两个字节数据的一位,每一个位代表一种控制,如要取多种控制时可用(2)运算符来合成,放在一个(3)访问限制的(4)数中。所以这些格式控制符必须通过类ios的(5)来访问。答案:(1)公有的无名的枚举类型(2)或“|”(3)保护(4)一个长整型数(5)公共接口(函数)9.1.4取代麻烦的流格式控制成员函数,可采用(1),其中有参数的,必须规定包含(2)头文献。答案:(1)流操作子(2)iomanip9.1.5通常标准设备输入指(1)。标准设备输出指(2)。答案:(1)键盘(2)显示屏9.1.6EOF为(1)标志,在iostream.h中定义EOF为(2),在intget()函数中读入表白输入流结束标志(3),函数返回(4)。答案:(1)文献结束标志(2)-1(3)^Z(Ctrl-Z)(4)EOF9.1.7C++根据文献内容的(1)可分为两类(2)和(3),前者存取的最小信息单位为(4),后者为(5)。答案:(1)数据格式(2)文本文献(3)二进制文献(4)字符(5)字节9.1.8当系统需要读入数据时是从(1)文献读入,即(2)操作。而系统要写数据时,是写到(3)文献中,即(4)操作。答案:(1)输入(2)提取(3)输出(4)插入9.1.9在面向对象的程序设计中,C++数据存入文献称作(1),而由文献获得数据称作(2)。按常规前者往往放在(3)函数中,而后者放在(4)函数中。答案:(1)把对象存入文献(2)由文献重构对象(3)析构函数(4)构造函数9.1.10文献的读写可以是随机的,意思是(1),也可以是顺序的,意思是(2)或(3)。答案:(1)可以从文献任何位置进行读写(2)从文献头开始(3)从尾部续上C++把每一个文献都当作一个(1)流,并以(2)结束。对文献读写事实上受到(3)指针的控制,输入流的指针也称为(4),每一次提取从该指针所指位置开始。输出流的指针也称为(5),每一次插入也从该指针所指位置开始。每次操作后自动将指针向文献尾移动。假如能任意向前向后移动该指针,则可实现(6)。答案:(1)有序的字节(2)文献结束符(endoffilemarker)(3)文献定位(4)读指针(5)写指针(6)随机读写简答题因cin为缓冲流,当键盘一次输入数据过多,保存在缓冲区中了,但这些数据也许是错的,希望清空它,以便下一次规定输入时,按提醒对的输入,应当如何办?答:只能读空缓冲区。流状态标志字state各位代表了什么?如何使用?答:全0,goodbit=0x00,流正常第1位为1,eofbit=0x01,输入流结束,忽略后继提取操作;或文献结束,已无数据可取第2位为1,failbit=0x02,最近的I/O操作失败,流可恢复第3位为1,badbit=0x04,最近的I/O操作非法,流可恢复第4位为1,hardfail=0x08,I/O出现致命错误,流不可恢复,VC++6.0不支持采用成员函数进行操作:intios::rdstate()const{returnstate;}//读取状态字intios:operator!()const{returnstate&(badbit|failbit);}//可用操作符!()代替fail()intios::bad(){returnstate&badbit;}//返回非法操作位voidios::clear(int_i){lock();state=_i;unlock();}//人工设立状态,可用来清状态intios::eof()const{returnstate&eofbit;}//返回流(文献)结束位intios::fail()const{returnstate&(badbit|failbit);}//返回操作非法和操作失败这两位intios::good()const{returnstate==0;}//正常返回1,否则返回0为什么cin输入时,空格和回车无法读入?这时可改用哪些流成员函数?答:由于空格和回车都可以作为数据之间的分格符,当输入串时空格和回车无法读入。可改用cin.get()和cin.getline()等流成员函数。在用cin输入结束时键入^Z,则程序对以后的输入如何解决?假如规定恢复正常,应执行什么成员函数?答:不再理睬以后的所有输入。可执行成员函数:cin.clear(0);使流恢复正常当输出字符串数组名时,输出的是串内容,有何办法可以输出串的首地址?答:将字符指针强制转换为泛型指针可以输出字符串地址文献的使用,有它的固定格式,请做简朴介绍。答:1.说明一个文献流对象,又被称为内部文献,如:fstreamiofile;2.用文献流对象的成员函数打开一个磁盘文献。打开文献的成员函数的第一个参数为要打开的磁盘文献名。第二个参数为打开方式,有输入(in),输出(out)等,打开方式在ios基类中定义为枚举类型。如:iofile.open(“myfile.txt”,ios::in|ios::out);1,2两步可合成如下:fstreamiofile(”myfile.txt”,ios::in|ios::out);3.使用提取和插入运算符对文献进行读写操作,或使用成员函数进行读写。4.关闭文献。当打开一个文献进行读写后,应当显式地关闭该文献如:iofile.close();在ios类中定义的文献打开方式中,公有枚举类型open_mode的各成员代表什么文献打开方式?答:in=0x01,//打开文献用于输入操作(从文献读取),如文献不存在则返回失败 out=0x02,//打开文献用于输出操作(写入文献)(缺省方式)//如文献存在,未同时设app,ate,in则文献清空 ate=0x04, //打开文献用于输入/输出,文献指针在文献尾,但新数据可写到任何位置 app=0x08,//打开文献用于输出,但从尾部添加,新数据只能添加在尾部 trunce=0x10,//打开文献,并清空它,不存在则建立新文献 binary=0x80//以二进制方式打开文献文本文献可以按行也可以按字符进行拷贝,在使用中为保证完整地拷贝各要注意哪些问题?答:按字符进行拷贝一方面必须设立关闭跳过空白(如:iofile.unsetf(ios::skipws)),由于提取(“>>”)运算符在缺省情况下是跳过空白(涉及空格,制表,backspace和回车等)的,这样拷贝的文献会缺少一些字符。第二,该程序应能拟定文献是否拷贝结束。按行进行拷贝,getline()回车换行符并不放在buf中,因此要加一个回车换行符。对文献流,“!”运算符完毕什么功能?答:返回状态字state操作非法和操作失败这两位。二进制文献读函数read()能否知道文献是否结束?应如何判断文献结束?答:读函数并不能知道文献是否结束,可用状态函数intios::eof()来判断文献是否结束。必须指出系统是根据当前操作的实际情况设立状态位,如需根据状态位来判断下一步的操作,必须在一次操作后立即去调取状态位,以判断本次操作是否有效。由二进制文献和文本文献来保存对象各有什么优点和缺陷?答:使用二进制文献,可以控制字节长度,读写数据时不会出现二义性,可靠性高。同时不知格式是无法读取的,保密性好。文献结束后,系统不会再读(见eofbit的说明),但程序不会自动停下来,所以要判断文献中是否已没有数据。使用文本文献来保存对象,操作简朴,但谁都可以读取这些数据,无保密性。文献的随机访问为什么总是用二进制文献,而不用文本文献?答:在C++中可以由程序来实现文献指针的移动,从而实现文献的随机访问,即可读写流中任意一段内容。一般文本文献很难准拟定位,所以随机访问多用于二进制文献。如何使用istream和ostream的成员函数来实现随机访问文献?答:在ios类中说明了一个公有枚举类型:enumseek_dir{ beg=0,//文献开头 cur=1,//文献指针的当前位置 end=2//文献结尾};istream类中提供了如下三个成员函数:istream&istream::seekg(streampos);//指针直接定位istream&istream::seekg(streamoff,ios::seek_dir);//指针相对定位longistream::tellg();//返回当前指针位置seekg(streamoff,ios::seek_dir)应用最广,如: datafile.seekg(-20L,ios::cur);表达将文献定位指针从当前位置向文献头部方向移20个字节。 datafile.seekg(20L,ios::beg);表达将文献定位指针从文献头向文献尾方向移20个字节。 datafile.seekg(-20L,ios::end);表达将文献定位指针从文献尾向文献头方向移20个字节。tellg()和seekg()往往配合使用。ostream类也提供了三个成员函数管理文献定位指针,它们是:ostream&ostream::seekp(streampos);ostream&ostream::seekp(streamoff,ios::seek_dir);longostream::tellp();定位指针只有一个但函数有两组,这两组个函数功能完全同样。编程与综合练习题编程实现以下数据输入输出:以左对齐方式输出整数,域宽为12;以八进制、十进制、十六进制输入输出整数;实现浮点数的指数格式和定点格式的输入输出,并指定精度;把字符串读入字符型数组变量中,从键盘输入,规定输入串的空格也所有读入,以回车换行符结束;以上规定用流成员函数和流操作子各做一遍。解:特别注意flags()和setf()的使用方法。注意注释。#include<iostream>#include<iomanip>usingnamespacestd;intmain(void){ intinum1=255,inum2=8191,inum3=65535; doublefnum=31.,fnum1; charstr[255]; cout<<"以左对齐方式输出整数,域宽为12:"<<endl; cout.flags(ios::left); cout.width(12);cout<<inum1; cout.width(12);cout<<inum2; cout.width(12);cout<<inum3<<endl; cout.flags(ios::left|ios::oct|ios::showbase);//或(cout.flags()|ios::oct|ios::showbase) cout.width(12);cout<<inum1; cout.width(12);cout<<inum2; cout.width(12);cout<<inum3<<endl; cout.setf(ios::hex,ios::hex|ios::oct);//或cout.setf(ios::hex);cout.unsetf(ios::oct); //特别注意第二个参数要包含第一个参数,否则两个参数位置上的位全清零,结果错 cout.width(12);cout<<inum1; cout.width(12);cout<<inum2; cout.width(12);cout<<inum3<<endl; cout.precision(10);//精度为10位,小数点后10位 cout.setf(ios::scientific,ios::floatfield);//floatfield为0x1800 cout<<"科学数表达方式:"<<fnum<<'\n'; cout.setf(ios::fixed,ios::floatfield);//设为定点,取消科学数方式 cout<<"定点表达方式:"<<fnum<<'\n'; cout<<"请输入PI:"<<endl; cin.precision(4); cin>>fnum1;//输入3. cout<<fnum1<<'\n';//由输出看输入精度无作用 cin.get();//吸取回车 cout<<"请输入一个字符串:"<<endl; cin.getline(str,255); cout<<str<<endl; cout.flags(0); cout<<"以左对齐方式输出整数,域宽为12:"<<endl; cout<<left<<dec<<setw(12)<<inum1; cout<<setw(12)<<inum2; cout<<setw(12)<<inum3<<endl; cout<<showbase<<oct<<setw(12)<<inum1; cout<<setw(12)<<inum2; cout<<setw(12)<<inum3<<endl; cout<<hex<<setw(12)<<inum1; cout<<setw(12)<<inum2; cout<<setw(12)<<inum3<<endl; cout<<setprecision(10)<<scientific<<"科学数表达方式:"<<fnum<<'\n'; cout<<fixed<<"定点表达方式:"<<fnum<<'\n';//精度10位,指小数点后10位 return0;}修改【例9.3】,增长一个字符串输入后规定确认,以保证输入的字符串(如姓名、地址等)无误。解:#include<iostream>usingnamespacestd;intmain(void){ charch,str[255]; do{ cout<<"请输入一个字符串:"<<endl; cin.getline(str,255); cout<<str<<endl; cout<<"输入对的吗?YorN"<<endl; cin>>ch; cin.get();//吸取输入YorN时留下的回车 }while(!(ch=='Y'||ch=='y')); cout<<"输入对的:"<<endl; cout<<str<<endl; return0;}重载学生类的“<<”和“>>”运算符。#include<fstream>#include<iostream>#include<string>#include<iomanip>usingnamespacestd;classstudent{ intid;//学号 stringname;//姓名 charsex;//性别 intage;//年龄 stringaddress;//家庭地址 floateng,phy,math,electron;//英语,物理,数学和电子学成绩public: student(int=0,string="#",char='#',int=0,string="#",float=0,float=0,float=0,float=0); friendostream&operator<<(ostream&dest,student&st);//重载插入运算符 friendistream&operator>>(istream&sour,student&st);//重载提取运算符};//流类作为形式参数必须是引用student::student(inti,stringn,chars,inta,stringadd,floaten,floatph,floatma,floatele){ id=i; name=n; sex=s; age=a; address=add; eng=en;phy=ph;math=ma;electron=ele;}ostream&operator<<(ostream&dest,student&st){//重载插入运算符 dest<<st.id<<'\t'<<<<'\t'<<st.sex<<'\t'<<st.age<<'\t'<<st.address<<'\t' <<st.eng<<'\t'<<st.phy<<'\t'<<st.math<<'\t'<<st.electron<<endl; returndest;}istream&operator>>(istream&sour,student&st){//重载提取运算符 cout<<"请输入学号:"<<endl; sour>>st.id; cout<<"请输入姓名:"<<endl; sour>>; cout<<"请输入性别:"<<endl; sour>>st.sex; cout<<"请输入年龄:"<<endl; sour>>st.age; cout<<"请输入地址:"<<endl; sour>>st.address; cout<<"请输入英语、物理、数学、电子各科成绩:"<<endl; sour>>st.eng>>st.phy>>st.math>>st.electron; returnsour;}intmain(){ studentst1,st2(2104105,"陈英",'m',19,"黄山路380号",89,78,90,96); cin>>st1; cout<<st1<<st2; return0;}发挥你的想象力,重载复数的“>>”运算符,对所有也许的错误都能规定重输。解:#include<iostream>usingnamespacestd;classComplex{ doubleReal,Image;public: Complex(doubler=0.0,doublei=0.0):Real(r),Image(i){};//定义构造函数 //见【例5.7】,这里省略,以节约篇幅 friendostream&operator<<(ostream&s,constComplex&z); friendistream&operator>>(istream&s,Complex&a);};//流类作为形式参数必须是引用ostream&operator<<(ostream&s,constComplex&z){ returns<<'('<<z.Real<<','<<z.Image<<')';}istream&operator>>(istream&s,Complex&a){//格式为r;r,i;(r);(r,i);整个复数输完才可回车 //容错强,如:sd(fr56cv,s79nml,45)i,78回车可对的判读为(56,79) doublere=0,im=0; charc=0; do{ s>>c; }while(c!='('&&c!='.'&&!(c>='0'&&c<='9'));//读空括号或数字前的无用字符 if(c=='('){ do{ s>>c; }while(c!='.'&&!(c>='0'&&c<='9'));//读空数字串前的无用字符 s.putback(c);//返回一个字符到输入缓冲区 s>>re;//实部 do{ s.get(c);//由于也许是回车 }while(c!='\n'&&c!=')'&&c!=',');//读空数字串后的无用字符 if(c==','){ do{//只读数字串 s>>c; }while(c!='.'&&!(c>='0'&&c<='9')); s.putback(c); s>>im;//虚部 do{ s.get(c);//由于也许是回车 }while(c!='\n'&&c!=')');//读空数字串后的无用字符 } elseim=0;//无此步,第二次赋值犯错 if(c!=')')s.clear(ios::failbit);//漏了括号给一个操作失败标志 } else{ s.putback(c);//无括号,返回一个字符到输入缓冲区 s>>re;//实部 do{ s.get(c);//由于也许是回车 }while(c!='\n'&&c!=',');//读空数字串后的无用字符 if(c==','){ do{//只读数字串 s>>c; }while(c!='.'&&!(c>='0'&&c<='9')); s.putback(c); s>>im;//虚部 do{ s.get(c);//由于也许是回车 }while(c!='\n');//读空数字串后的无用字符 } elseim=0;//无此步,第二次赋值犯错 } if(s)a=Complex(re,im); returns;}intmain(){ Complexa,b,c,d; cout<<"输入一个实数"<<endl; cin>>a; cout<<"输入一个复数"<<endl; cin>>b; cout<<"输入一个用括号括起来的实数"<<endl; cin>>c; cout<<"输入一个用括号括起来复数"<<endl; cin>>d; cout<<"a="<<a<<'\t'<<"b="<<b<<'\t'<<"c="<<c<<'\t'<<"d="<<d<<'\n'; return0;}以文本方式把一个文本文献(如C++源文献)的前十行拷贝到一个新的文献中。解:注意只能用于纯文本文献,如用于word文献则失败。word文档构造前面有一大堆说明,按文本读必然失败。第二,用传统的运营库,按行读有也许丢失一些回车,而用新的标准库则解决了这个问题。用VC++标准库函数,即用头文献iostream时,假如函数未能读到结束字符而停止,流犯错(输入输出操作失败),后面不再读入,必须清0流状态字,才干继续读入。一行字符分几次读完,本来有也许无法判断是读到结束字符结束还是读到指定字符结束,现在可以判断了:假如流正常,则读到了结束字符。#include<fstream>#include<iostream>//<fstream.h>不包含<iostream.h>#include<cstdlib>usingnamespacestd;intmain(){ intline=0; charfilename[256],buf[256]; fstreamsfile,dfile; cout<<"输入源文献途径名:"<<endl;//请用s.txt,如用s.doc(word文档)则失败 cin>>filename;//对途径各方面而言空格是无关紧要的,否则要用getline()等成员函数 sfile.open(filename,ios::in);//打开一个已存在的文献 while(!sfile){ cout<<"源文献找不到,请重新输入途径名:"<<endl; sfile.clear(0);//犯错后,状态必须清0 cin>>filename; sfile.open(filename,ios::in); } cout<<"输入目的文献途径名:"<<endl;//请用d.txt cin>>filename;//只能创建文献,不能建立子目录,如途径不存在则失败 dfile.open(filename,ios::out); if(!dfile){ cout<<"目的文献创建失败"<<endl; return1; } while(sfile.getline(buf,256),sfile.eof()!=1&&line<10){//按行拷贝A行 if(sfile.rdstate()==0){ dfile<<buf<<'\n';//因流正常,读到回车符,但未提取B行 line++; } else{ dfile<<buf;//流不正常,尚未读到回车换行符,所以不加'\n' sfile.clear();//状态字被置为0x02,必须清0 } } sfile.close(); dfile.close(); return0;}用二进制方式,把一个文献连接到另一个文献的尾部,选择适当的文献打开方式完毕。解:注意连接只能用于纯文本文献,如用于word文献则失败。假如用word文档,则可见目的文档大小在翻倍,但只能读最前面一段。由于word文档构造前面有一大堆说明,真正连接时,后面的源文献前面的说明要去掉,但这做不到。#include<fstream>#include<iostream>#include<cstdlib>usingnamespacestd;intmain(){ intn; charfilename[256],buf[100]; fstreamsfile,dfile; cout<<"输入源文献途径名:"<<endl;//请用s.txt cin>>filename;//对途径各方面而言空格是无关紧要的,否则要用getline()等成员函数 sfile.open(filename,ios::in|ios::binary);//打开一个已存在的二进制文献 while(!sfile){ cout<<"源文献找不到,请重新输入途径名:"<<endl; sfile.clear(0);//犯错后,状态必须清0 cin>>filename; sfile.open(filename,ios::in|ios::binary); } cout<<"输入目的文献途径名:"<<endl;//请用d.txt,s.txt接于其后;用源文献,会死循环(A行) cin>>filename;//只能创建文献,不能建立子目录,如途径不存在则失败 dfile.open(filename,ios::app|ios::out|ios::binary);//文献指针在尾部 if(!dfile){ cout<<"目的文献创建失败"<<endl; return1; } while(!sfile.eof()){//二进制方式需另判文献是否结束A sfile.read(buf,100); n=sfile.gcount(); dfile.write(buf,n);//按实际读取字节数写 } sfile.close(); dfile.close(); return0;}同上题,采用重新定位文献指针方式来实现(随机访问方式)。解:同样连接只能用于纯文本文献,如用于word文献则失败。假如用word文档,则可见目的文档大小在翻倍,但只能读最前面一段。由于word文档构造前面有一大堆说明,真正链接时,后面的源文献前面的说明要去掉,但这做不到。#include<fstream>#include<iostream>#include<cstdlib>usingnamespacestd;intmain(){ intn; charfilename[256],buf[100]; fstreamsfile,dfile; cout<<"输入源文献途径名:"<<endl;//请用s.txt cin>>filename;//对途径各方面而言空格是无关紧要的,否则要用getline()等成员函数 sfile.open(filename,ios::in|ios::binary);//打开一个已存在的二进制文献 while(!sfile){ cout<<"源文献找不到,请重新输入途径名:"<<endl; sfile.clear(0);//犯错后,状态必须清0 cin>>filename; sfile.open(filename,ios::in|ios::binary); } cout<<"输入目的文献途径名:"<<endl;//请用d.txt,s.txt接于其后;用源文献,会死循环(A行) cin>>filename;//只能创建文献,不能建立子目录,如途径不存在则失败 dfile.open(filename,ios::in|ios::out|ios::binary);//打开输入输出文献 if(!dfile){ dfile.clear(0); dfile.open(filename,ios::out);//建立输出文献 dfile.close(); dfile.open(filename,ios::in|ios::out|ios::binary);//改为输入输出文献 } dfile.seekp(0,ios::end);//写指针重定位到文献尾,seekp和seekg是同一个文献指针 while(!sfile.eof()){//二进制方式需另判文献是否结束A sfile.read(buf,100); n=sfile.gcount(); dfile.write(buf,n);//按实际读取字节数写 } sfile.close(); dfile.close(); return0;}采用筛选法求100以内的所有素数(参见【例3.16】)。将所得数据存入文本文献和二进制文献。对送入文本文献中的素数,规定存放格式是每行10个素数,每个数占6个字符,左对齐;可用任一文本编辑器将它打开阅读。二进制文献整型数的长度请用sizeof()来获得,规定可以正序读出,也可以逆序读出(运用文献定位指针移动实现),读出数据按文本文献中的格式输出显示。解:前半题文本文献与习题3.17相同,只是那里是右对齐,这里只新做了二进制文献。注意逆序输出前,试读看有多少数据时,一旦读到文献结束,eofbit=1,不清0,后面操作不能进行。#include<fstream.h>#include<iomanip.h>#include<math.h>constintn=100;voidmain(){ ofstreamofile; ifstreamifile; inta[n],i,j; charch,b[256]; for(i=0;i<n;i++)a[i]=1+i; //用数组保存整数1-100 a[0]=0; //1不是素数,置0 for(i=0;i<n;i++){ if(a[i]==0)continue; //该数已经置0,判断下一个数 for(j=i+1;j<n;j++)if(a[j]%a[i]==0)a[j]=0; //是a[i]倍数的元素置0; } ofile.open("myfile9_9.txt"); intcount=0; ofile.flags(ios::left); ofile<<"1-"<<n<<"之间的素数:"<<endl; for(i=0;i<n;i++) //输出所有素数 if(a[i]!=0){ ofile<<setw(6)<<a[i]; count++; if(count%10==0)ofile<<endl; //每行10个数据 } ofile.close(); cout<<"是否要将文本文献输出?Y或N"<<endl; cin>>ch; if(ch=='y'||ch=='Y'){ ifile.open("myfile9_9.txt"); i=0; while(ifile.get(b[i])){//读标题,不可用>>,它不能读白字符, if(b[i]=='\n')break; i++; } b[i]='\0'; cout.flags(ios::left); cout<<b<<endl; count=0; while(1){ ifile>>i;//由文献读入 if(ifile.eof()!=0)break; cout<<setw(6)<<i;//屏幕显示 count++; if(count%10==0)cout<<endl; //每行10个数 } ifile.close(); cout<<endl; } ofile.open("myfile9_9.dat",ios::out|ios::binary); for(i=0;i<n;i++) //输出所有素数 if(a[i]!=0){ ofile.write((char*)&a[i],sizeof(int)); } ofile.close(); cout<<"是否要将二进制文献输出?Y或N"<<endl; cin>>ch; if(ch=='y'||ch=='Y'){ count=0; ifile.open("myfile9_9.dat",ios::in|ios::binary); while(1){ ifile.read((char*)&i,sizeof(int)); if(ifile.eof()!=0)break; cout<<setw(6)<<i;//屏幕显示 count++; if(count%10==0)cout<<endl; } ifile.close(); cout<<endl; } cout<<"是否要将二进制文献逆序输出?Y或N"<<endl; cin>>ch; if(ch=='y'||ch=='Y'){ count=0; ifile.open("myfile9_9.dat",ios::in|ios::binary); while(1){ ifile.read((char*)&i,sizeof(int)); if(ifile.eof()!=0)break; count++; } ifile.clear(0);//当文献读完时,eofbit=1,不清0,后面的操作不能进行 ifile.seekg(-4,ios::end); for(j=1;j<=count;j++){ ifile.read((char*)&i,sizeof(int)); cout<<setw(6)<<i;//屏幕显示 if(j%10==0)cout<<endl; ifile.seekg(-8,ios::cur); } ifile.close(); cout<<endl; }}正弦函数在0o~90o的范围中是单调递增的,建立两个文献:一个放sin0o,sin2o,…,sin80o;另一个放sin1o,sin3o,…,sin79o,sin81o,sin82o,…,sin90o,用归并法,把这两个数据文献合并为升序排序的文献,重组为一个完整的sin()函数表文献。解:题解中注释掉的直接读写法与使用成员函数结果完全相同,对于类对象,读和写及占据内存大小均指数据成员。主函数中要避免第2次运营时表中出现反复数据。#include<cmath>#include<fstream>#include<iostream>#include<iomanip>usingnamespacestd;classsinx{ doubleDegree;//角度 doubleValue;//正弦值public: sinx(double=0); voiddisplay(); voidBdatatofile(fstream&);//文献流类作为形式参数必须是引用 voidBdatafromfile(fstream&); voiddatainput(doubledeg); booloperator<=(sinx&); booloperator==(sinx&);};boolsinx::operator<=(sinx&si){ doublek; k=Degree-si.Degree; if(k<=0)returntrue; elsereturnfalse;}boolsinx::operator==(sinx&si){ doublek; k=Degree-si.Degree; if(k==0)returntrue; elsereturnfalse;}sinx::sinx(doubledeg){ Degree=deg; Value=sin(deg*3./180);}voidsinx::display(){ cout<<setw(10)<<Degree<<setw(10)<<Value<<endl;}voidsinx::datainput(doubledeg){ Degree=deg; Value=sin(deg*3./180);}voidsinx::Bdatatofile(fstream&dest){ dest.write((char*)&Degree,sizeof(double)); dest.write((char*)&Value,sizeof(double));}voidsinx::Bdatafromfile(fstream&sour){ sour.read((char*)&Degree,sizeof(double)); sour.read((char*)&Value,sizeof(double));}//由此可见读和写是完全对称的过程,顺序决不能错template<typenameT>classArray{ T*elements; charname[20]; intSubscript;//已用最大下标值 intmaxSize; fstreamdatafile;public: Array(char*="myfile",int=20); ~Array(); boolIsFull()const{returnSubscript==maxSize-1;} voidrenews();//数组扩大一倍 voidordinsert(T&);//升序输入 voidlistshow();//显示数组};template<typenameT>Array<T>::Array(char*filename,intmaxs){ maxSize=maxs; Subscript=-1;//私有数据不允许直接赋初值,必须在构造函数中赋初值 strcpy(name,filename); Ttemp; elements=newT[maxSize]; datafile.open(name,ios::binary|ios::in); if(!datafile==0){ while(!datafile.eof()){ temp.Bdatafromfile(datafile); // datafile.read((char*)&temp,sizeof(T));//直接读写法与使用成员函数结果相同 if(datafile.eof()==0){//读到无数据可读后,即读入不成功,eofbit为1 ordinsert(temp); } } datafile.close(); } datafile.clear(0);//采用标准库不可少,前面读到过文献结束或打开文献失败,无法恢复}template<typenameT>Array<T>::~Array(){ inti; datafile.open(name,ios::binary|ios::out); for(i=0;i<=Subscript;i++) elements[i].Bdatatofile(datafile);// datafile.write((char*)&elements[i],sizeof(T));//直接读写法与使用成员函数结果相同 datafile.close(); delete[]elements;}template<typenameT>voidArray<T>::renews(){ inti; T*temp=elements; maxSize*=2; elements=newT[maxSize]; for(i=0;i<=Subscript;i++)elements[i]=temp[i]; delete[]temp;}template<typenameT>voidArray<T>::ordinsert(T&elem){//以角度为关键字排序 inti,j; if(IsFull())renews(); for(i=0;i<=Subscript;i++)if(elem<=elements[i])break; if(!(elem==elements[i])){ for(j=Subscript;j>=i;j--)elements[j+1]=elements[j]; Subscript++; } if(Subscript==-1)Subscript++;//考虑到进入的第一项 elements[i]=elem;}template<typenameT>voidArray<T>::listshow(){ inti; for(i=0;i<=Subscript;i++)elements[i].display();}//两个文献归并用独立的函数模板template<typenameT>voidMerge(char*filename1,char*filename2,char*filename){ fstreamsdatafile1(filename1,ios::out|ios::in|ios::binary); fstreamsdatafile2(filename2,ios::out|ios::in|ios::binary); fstreamddatafile(filename,ios::out|ios::binary); inti=0,j=0,k=0,ns1,ns2; Ttemps1,temps2; while(sdatafile1.eof()==0){//侧元素数量,注意会多余一个 sdatafile1.read((char*)&temps1,sizeof(T)); i++; } ns1=i-1; cout<<"表1元素数"<<ns1<<endl; while(sdatafile2.eof()==0){ sdatafile2.read((char*)&temps2,sizeof(T)); j++; } ns2=j-1; cout<<"表2元素数"<<ns2<<endl; sdatafile1.clear(0);//用随机方式,一旦用顺序文献方式访问到结束,就必须清状态 sdatafile2.clear(0);i=0; j=0; sdatafile1.seekg(0,ios::beg); sdatafile2.seekg(0,ios::beg);// sdatafile1.read((char*)&temps1,sizeof(T));//此方法与用成员函数完全相同// sdatafile2.read((char*)&temps2,sizeof(T));//对于类对象,读和写及大小均仅指数据成员 temps1.Bdatafromfile(sdatafile1); temps2.Bdatafromfile(sdatafile2); while(i<ns1&&j<ns2){ if(temps1<=temps2){// ddatafile.write((char*)&temps1,sizeof(T));// sdatafile1.read((char*)&temps1,sizeof(T)); temps1.Bdatatofile(ddatafile); temps1.Bdatafromfile(sdatafile1); i++; } else{// ddatafile.write((char*)&temps2,sizeof(T));//对象读和写及大小均仅指数据成员// sdatafile2.read((char*)&temps2,sizeof(T));//此方法与用成员函数完全相同 temps2.Bdatatofile(ddatafile); temps2.Bdatafromfile(sdatafile2); j++; } } while(i<ns1){//复制第一个表的剩余元素// ddatafile.write((char*)&temps1,sizeof(T));// sdatafile1.read((char*)&temps1,sizeof(T)); temps1.Bdatatofile(ddatafile); temps1.Bdatafromfile(sdatafile1); i++; } while(j<ns2){//复制第二个表的剩余元素// ddatafile.write((char*)&temps2,sizeof(T));// sdatafile2.read((char*)&temps2,sizeof(T)); temps2.Bdatatofile(ddatafile); temps2.Bdatafromfile(sdatafile2); j++; } sdatafile1.close(); sdatafile2.close(); ddatafile.close();} intmain(){ sinxtemp; inti; {//两个正弦表分别在两个块域中定义,域结束时对象存入文献 Array<sinx>mylist("mydata1"); cout<<"建立正弦表1(0,2,4,~80度)"<<endl; for(i=0;i<=80;i=i+2){ temp.datainput(i); mylist.ordinsert(temp);//除排序外,同时保证二次进入时不会有反复的表项 } mylist.listshow(); } { Array<sinx>mylist("mydata2");cout<<"建立正弦表2(1,3,5,~81度;82,83,~90)"<<endl; for(i=82;i<=90;i++){ temp.datainput(i); mylist.ordinsert(temp); } for(i=1;i<=81;i=i+2){//注意较小的数后入 temp.datainput(i); mylist.ordinsert(temp); } mylist.listshow(); } Merge<sinx>("mydata1","mydata2","mydata");//按题意规定两个文献归并直接使用文献 Array<sinx>mylist("mydata"); cout<<"输出正弦表(0,1,~90度)"<<endl; mylist.listshow(); return0;} 解2:本例未用链表类,但用函数模板。题解中使用的直接读写法与成员函数结果完全相同,对于类对象,读和写及占据内存大小均指数据成员。#include<cmath>#include<fstream>#include<iostream>#include<iomanip>usingnamespacestd;classsinx{ doubleDegree;//角度 doubleValue;//正弦值public: sinx(double=0); voiddisplay(); voiddatainput(doubledeg); booloperator<=(sinx&); booloperator==(sinx&);};boolsinx::operator<=(sinx&si){ doublek; k=Degree-si.Degree; if(k<=0)returntrue; elsereturnfalse;}boolsinx::operator==(sinx&si){ doublek; k=Degree-si.Degree; if(k==0)returntrue; elsereturnfalse;}sinx::sinx(doubledeg){ Degree=deg; Value=sin(deg*3./180);}voidsinx::display(){ cout<<setw(10)<<Degree<<setw(10)<<Value<<endl;}voidsinx::datainput(doubledeg){ Degree=deg; Value=sin(deg*3./180);}template<typenameT>voidlistshow(T*elements,intsubsc){ inti; for(i=0;i<=subsc;i++)elements[i].display();}template<typenameT>voidordinsert(T&elem,T*elements,intsubsc){//以角度为关键字排序 inti,j; for(i=0;i<=subsc-1;i++)if(elem<=elements[i])break; if(!(elem==elements[i])){ for(j=subsc-1;j>=i;j--)elements[j+1]=elements[j]; } elements[i]=elem;}template<typenameT>intreadfile(char*filename,T*elements){//文献写入链表,返回最大下标 intk=-1; Ttemp; ifstreamdatafile; datafile.open(filename,ios::binary|ios::in); while(!datafile.eof()){ datafile.read((char*)&temp,sizeof(T));if(datafile.eof()==0){//读到无数据可读后,即读入不成功,eofbit为1 k++; ordinsert(temp,elements,k); } } datafile.close(); returnk;}template<typenameT>voidwritefile(char*filename,T*elements,intsubsc){ inti; ofstreamdatafile; datafile.open(filename,ios::binary|ios::out); for(i=0;i<=subsc;i++) datafile.write((char*)&elements[i],sizeof(T)); datafile.close();}//两个文献归并用独立的函数模板template<typenameT>voidMerge(char*filename1,char*filename2,char*filename){ fstreamsdatafile1(filename1,ios::out|ios::in|ios::binary); fstreamsdatafile2(filename2,ios::out|ios::in|ios::binary); fstreamddatafile(filename,ios::out|ios::binary); inti=0,j=0,k=0,ns1,ns2; Ttemps1,temps2; while(sdatafile1.eof()==0){//求文献所含数据数量 sdatafile1.read((char*)&temps1,sizeof(T)); i++; } ns1=i-1; while(sdatafile2.eof()==0){ sdatafile2.read((char*)&temps2,sizeof(T)); j++; } ns2=j-1; sdatafile1.clear(0); sdatafile2.clear(0);i=0; j=0; sdatafile1.seekg(0,ios::beg); sdatafile2.seekg(0,ios::beg); sdatafile1.read((char*)&temps1,sizeof(T));//此方法与用成员函数完全相同 sdatafile2.read((char*)&temps2,sizeof(T));//对于类对象,读和写及大小均仅指数据成员 while(i<ns1&&j<ns2){ if(temps1<=temps2){ ddatafile.write((char*)&temps1,sizeof(T)); sdatafile1.read((char*)&temps1,sizeof(T)); i++; } else{ ddatafile.write((char*)&temps2,sizeof(T));//对象读和写及大小均仅指数据成员 sdatafile2.read((char*)&temps2,sizeof(T));//此方法与用成员函数完全相同 j++; } } while(i<ns1){//复制第一个表的剩余元素 ddatafile.write((char*)&temps1,sizeof(T)); sdatafile1.read((char*)&temps1,sizeof(T)); i++; } while(j<ns2){//复制第二个表的剩余元素 ddatafile.write((char*)&temps2,sizeof(T)); sdatafile2.read((char*)&temps2,sizeof(T)); j++; } sdatafile1.close(); sdatafile2.close(); ddatafile.close();}intmain(){ sinxtemp,list1[100],list2[100],list[100]; inti,k1,k2,k3; cout<<"建立正弦表1(0,2,4,~80度)"<<endl; k1=-1; for(i=0;i<=80;i=i+2){ temp.datainput(i); k1++; ordinsert(temp,list1,k1);//除排序外,同时保证二次进入时不会有反复的表项 } writefile("mydata1",list1,k1); temp.datainput(0); for(i=0;i<=k1;i++)list1[i]=temp;//数组清空,以便检查文献 k1=readfile("mydata1",list1);//由文献重新写入数组 listshow(list1,k1); cout<<"建立正弦表2(1,3,5,~81度;82,83,~90度)"<<endl; k2=-1; for(i=82;i<=90;i++){ temp.datainput(i); k2++; ordinsert(temp,list2,k2); } for(i=1;i<=81;i=i+2){ temp.datainput(i); k2++; ordinsert(temp,list2,k2);//除排序外,同时保证二次进入时不会有反复的表项 } writefile("mydata2",list2,k2); temp.datainput(0); for(i=0;i<=k2;i++)list2[i]=temp;//数组清空,以便检查文献 k2=readfile("mydata2",list2);//由文献重新写入数组 listshow(list2,k2);Merge<sinx>("mydata1","mydata2","mydata");//按题意规定两个文献归并直接使用文献 cout<<"输出正弦表(0,1,~90度)"<<endl; k3=readfile("mydata",list);//由文献重新写入数组 listshow(list,k3); return0;}将学校里的学生,定义为一个学生数组类,数组对象动态建立,初始为3个元素,不够用时扩充一倍。规定放在构造函数中用二进制数据文献建立数组元素对象,在析构函数中保存数据和关闭文献。第一次运营时,建立空的数据文献,由键盘输入建立数组元素对象,并写入文献,程序退出时,关闭文献;下一次运营时就可以由文献构造对象,恢复前一次做过的工作。解:#include<fstream>#include<iostream>#include<string>#include<iomanip>usingnamespacestd;classstudent{ intid;//学号 stringname;//姓名 charsex;//性别 intage;//年龄 stringaddress;//家庭地址 floateng,phy,math,electron;//英语,物理,数学和电子学成绩public: student(int=0,string="#",char='#',int=0,string="#",float=0,float=0,float=0,float=0); voidBdatatofile(fstream&dest);//数据写入文献流类 voidBdatafromfile(fstream&sour);//由文献流类读出数据 booloperator<=(student&ele){returnid<=ele.id;} booloperator==(student&ele){returnid==ele.id;} friendostream&operator<<(ostream&dest,student&st);//重载插入运算符 friendistream&operator>>(istream&sour,student&st);//重载提取运算符};student::student(inti,stringn,chars,inta,stringadd,floaten,floatph,floatma,floatele){ id=i; name=n; sex=s; age=a; address=add; eng=en;phy=ph;math=ma;electron=ele;}voidstudent::Bdatatofile(fstream&dest){//文献流类作为形式参数必须是引用 dest.write((char*)&id,sizeof(int)); dest.write(name.c_str(),20);//由string类的c_str()函数转为char* dest.write((char*)&sex,sizeof(char)); dest.write((char*)&age,sizeof(int)); dest.write(address.c_str(),20);//由string类的c_str()函数转为char* dest.write((char*)&eng,sizeof(float)); dest.write((char*)&phy,sizeof(float)); dest.write((char*)&math,sizeof(float)); dest.write((char*)&electron,sizeof(float));}voidstudent::Bdatafromfile(fstream&sour){//文献流类作为形式参数必须是引用 charDesc[20]; sour.read((char*)&id,si

温馨提示

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

评论

0/150

提交评论