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