第九章流类库和输入文档格式.docx
《第九章流类库和输入文档格式.docx》由会员分享,可在线阅读,更多相关《第九章流类库和输入文档格式.docx(39页珍藏版)》请在冰豆网上搜索。
(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)从尾部续上
9.1.11C++把每一个文件都看成一个
(1)流,并以
(2)结束。
对文件读写实际上受到(3)指针的控制,输入流的指针也称为(4),每一次提取从该指针所指位置开始。
输出流的指针也称为(5),每一次插入也从该指针所指位置开始。
每次操作后自动将指针向文件尾移动。
如果能任意向前向后移动该指针,则可实现(6)。
(1)有序的字节
(2)文件结束符(endoffilemarker)
(3)文件定位
(4)读指针
(5)写指针
(6)随机读写
9.2简答题
9.2.1因cin为缓冲流,当键盘一次输入数据过多,保存在缓冲区中了,但这些数据可能是错的,希望清空它,以便下一次要求输入时,按提示正确输入,应该怎样办?
答:
只能读空缓冲区。
9.2.2流状态标志字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;
}//读取状态字
operator!
()const{returnstate&
(badbit|failbit);
}//可用操作符!
()代替fail()
bad(){returnstate&
badbit;
}//返回非法操作位
voidios:
clear(int_i){lock();
state=_i;
unlock();
}//人工设置状态,可用来清状态
eof()const{returnstate&
eofbit;
}//返回流(文件)结束位
fail()const{returnstate&
}//返回操作非法和操作失败这两位
good()const{returnstate==0;
}//正常返回1,否则返回0
9.2.3为什么cin输入时,空格和回车无法读入?
这时可改用哪些流成员函数?
因为空格和回车都可以作为数据之间的分格符,当输入串时空格和回车无法读入。
可改用cin.get()和cin.getline()等流成员函数。
9.2.4在用cin输入结束时键入^Z,则程序对以后的输入怎样处理?
如果要求恢复正常,应执行什么成员函数?
不再理会以后的所有输入。
可执行成员函数:
cin.clear(0);
使流恢复正常
9.2.5当输出字符串数组名时,输出的是串内容,有何办法可以输出串的首地址?
将字符指针强制转换为泛型指针可以输出字符串地址
9.2.6文件的使用,有它的固定格式,请做简单介绍。
1.说明一个文件流对象,又被称为内部文件,如:
fstreamiofile;
2.用文件流对象的成员函数打开一个磁盘文件。
打开文件的成员函数的第一个参数为要打开的磁盘文件名。
第二个参数为打开方式,有输入(in),输出(out)等,打开方式在ios基类中定义为枚举类型。
如:
iofile.open(“myfile.txt”,ios:
in|ios:
out);
1,2两步可合成如下:
fstreamiofile(”myfile.txt”,ios:
3.使用提取和插入运算符对文件进行读写操作,或使用成员函数进行读写。
4.关闭文件。
当打开一个文件进行读写后,应该显式地关闭该文件如:
iofile.close();
9.2.7在ios类中定义的文件打开方式中,公有枚举类型open_mode的各成员代表什么文件打开方式?
in=0x01,//打开文件用于输入操作(从文件读取),如文件不存在则返回失败
out=0x02,//打开文件用于输出操作(写入文件)(缺省方式)
//如文件存在,未同时设app,ate,in则文件清空
ate=0x04,//打开文件用于输入/输出,文件指针在文件尾,但新数据可写到任何位置
app=0x08,//打开文件用于输出,但从尾部添加,新数据只能添加在尾部
trunce=0x10,//打开文件,并清空它,不存在则建立新文件
binary=0x80//以二进制方式打开文件
9.2.8文本文件可以按行也可以按字符进行拷贝,在使用中为保证完整地拷贝各要注意哪些问题?
按字符进行拷贝首先必须设置关闭跳过空白(如:
iofile.unsetf(ios:
skipws)),因为提取(“>
”)运算符在缺省情况下是跳过空白(包括空格,制表,backspace和回车等)的,这样拷贝的文件会缺少一些字符。
第二,该程序应能确定文件是否拷贝结束。
按行进行拷贝,getline()回车换行符并不放在buf中,因此要加一个回车换行符。
9.2.9对文件流,“!
”运算符完成什么功能?
返回状态字state操作非法和操作失败这两位。
9.2.10二进制文件读函数read()能否知道文件是否结束?
应怎样判断文件结束?
读函数并不能知道文件是否结束,可用状态函数intios:
eof()来判断文件是否结束。
必须指出系统是根据当前操作的实际情况设置状态位,如需根据状态位来判断下一步的操作,必须在一次操作后立即去调取状态位,以判断本次操作是否有效。
9.2.11由二进制文件和文本文件来保存对象各有什么优点和缺点?
使用二进制文件,可以控制字节长度,读写数据时不会出现二义性,可靠性高。
同时不知格式是无法读取的,保密性好。
文件结束后,系统不会再读(见eofbit的说明),但程序不会自动停下来,所以要判断文件中是否已没有数据。
使用文本文件来保存对象,操作简单,但谁都可以读取这些数据,无保密性。
9.2.12文件的随机访问为什么总是用二进制文件,而不用文本文件?
在C++中可以由程序来实现文件指针的移动,从而实现文件的随机访问,即可读写流中任意一段内容。
一般文本文件很难准确定位,所以随机访问多用于二进制文件。
9.2.13怎样使用istream和ostream的成员函数来实现随机访问文件?
在ios类中说明了一个公有枚举类型:
enumseek_dir{
beg=0,//文件开头
cur=1,//文件指针的当前位置
end=2//文件结尾
};
istream类中提供了如下三个成员函数:
istream&
istream:
seekg(streampos);
//指针直接定位
seekg(streamoff,ios:
seek_dir);
//指针相对定位
longistream:
tellg();
//返回当前指针位置
seekg(streamoff,ios:
seek_dir)应用最广,如:
datafile.seekg(-20L,ios:
cur);
表示将文件定位指针从当前位置向文件头部方向移20个字节。
datafile.seekg(20L,ios:
beg);
表示将文件定位指针从文件头向文件尾方向移20个字节。
end);
表示将文件定位指针从文件尾向文件头方向移20个字节。
tellg()和seekg()往往配合使用。
ostream类也提供了三个成员函数管理文件定位指针,它们是:
ostream&
ostream:
seekp(streampos);
seekp(streamoff,ios:
longostream:
tellp();
定位指针只有一个但函数有两组,这两组个函数功能完全一样。
二.编程与综合练习题
9.3编程实现以下数据输入输出:
a)以左对齐方式输出整数,域宽为12;
b)以八进制、十进制、十六进制输入输出整数;
c)实现浮点数的指数格式和定点格式的输入输出,并指定精度;
d)把字符串读入字符型数组变量中,从键盘输入,要求输入串的空格也全部读入,以回车换行符结束;
e)以上要求用流成员函数和流操作子各做一遍。
解:
特别注意flags()和setf()的使用方法。
注意注释。
#include<
iostream>
iomanip>
usingnamespacestd;
intmain(void){
intinum1=255,inum2=8191,inum3=65535;
doublefnum=31.415926535,fnum1;
charstr[255];
cout<
"
以左对齐方式输出整数,域宽为12:
endl;
cout.flags(ios:
left);
cout.width(12);
cout<
inum1;
inum2;
inum3<
left|ios:
oct|ios:
showbase);
//或(cout.flags()|ios:
showbase)
cout.setf(ios:
hex,ios:
hex|ios:
oct);
//或cout.setf(ios:
hex);
cout.unsetf(ios:
//特别注意第二个参数要包含第一个参数,否则两个参数位置上的位全清零,结果错
cout.precision(10);
//精度为10位,小数点后10位
scientific,ios:
floatfield);
//floatfield为0x1800
科学数表达方式:
fnum<
'
\n'
;
fixed,ios:
//设为定点,取消科学数方式
定点表达方式:
请输入PI:
cin.precision(4);
cin>
fnum1;
//输入3.1415926535
fnum1<
//由输出看输入精度无作用
cin.get();
//吸收回车
请输入一个字符串:
cin.getline(str,255);
str<
cout.flags(0);
left<
dec<
setw(12)<
showbase<
oct<
hex<
setprecision(10)<
scientific<
fixed<
//精度10位,指小数点后10位
return0;
}
9.4修改【例9.3】,增加一个字符串输入后要求确认,以保证输入的字符串(如姓名、地址等)无误。
charch,str[255];
do{
cout<
cin.getline(str,255);
输入正确吗?
YorN"
cin>
ch;
cin.get();
//吸收输入YorN时留下的回车
}while(!
(ch=='
Y'
||ch=='
y'
));
输入正确:
9.5重载学生类的“<
”和“>
”运算符。
fstream>
string>
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&
dist,student&
st);
//重载插入运算符
friendistream&
operator>
(istream&
sour,student&
//重载提取运算符
//流类作为形式参数必须是引用
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;
st){//重载插入运算符
dist<
st.id<
\t'
st.name<
st.sex<
st.age<
st.address<
<
st.eng<
st.phy<
st.math<
st.electron<
returndist;
st){//重载提取运算符
请输入学号:
sour>
st.id;
请输入姓名:
st.name;
请输入性别:
st.sex;
请输入年龄:
st.age;
请输入地址:
st.address;
请输入英语、物理、数学、电子各科成绩:
st.eng>
st.phy>
st.math>
st.electron;
returnsour;
intmain(){
studentst1,st2(2104105,"
陈英"
'
m'
19,"
黄山路380号"
89,78,90,96);
st1;
st1<
st2;
9.6发挥你的想象力,重载复数的“>
”运算符,对所有可能的错误都能要求重输。
classComplex{
doubleReal,Image;
Complex(doubler=0.0,doublei=0.0):
Real(r),Image(i){};
//定义构造函数
//见【例5.7】,这里省略,以节约篇幅
s,constComplex&
z);
s,Complex&
a);
s,constComplex&
z){
returns<
('
z.Real<
z.Image<
)'
s,Complex&
a){//格式为r;
r,i;
(r);
(r,i);
整个复数输完才可回车
//容错强,如:
sd(fr56cv,s79nml,45)i,78回车可正确判读为(56,79)
doublere=0,im=0;
charc=0;
s>
c;
}while(c!
='
&
c!
.'
!
(c>
0'
c<
9'
//读空括号或数字前的无用字符
if(c=='
){
do{
s>
}while(c!
//读空数字串前的无用字符
s.putback(c);
//返回一个字符到输入缓冲区
re;
//实部
s.get(c);
//因为可能是回车
);
//读空数字串后的无用字符
if(c=='
do{//只读数字串
s>
}while(c!
s.putback(c);
im;
//虚部
do{
s.get(c);
}
elseim=0;
//无此步,第二次赋值出错
if(c!
)s.clear(ios:
failbit);
//漏了括号给一个操作失败标志
}
else{
//无括号,返回一个字符到输入缓冲区
if(s)a=Complex(re,im);
returns;
Complexa,b,c,d;
输入