chapter8.docx

上传人:b****6 文档编号:8193213 上传时间:2023-01-29 格式:DOCX 页数:68 大小:148.81KB
下载 相关 举报
chapter8.docx_第1页
第1页 / 共68页
chapter8.docx_第2页
第2页 / 共68页
chapter8.docx_第3页
第3页 / 共68页
chapter8.docx_第4页
第4页 / 共68页
chapter8.docx_第5页
第5页 / 共68页
点击查看更多>>
下载资源
资源描述

chapter8.docx

《chapter8.docx》由会员分享,可在线阅读,更多相关《chapter8.docx(68页珍藏版)》请在冰豆网上搜索。

chapter8.docx

chapter8

第八章:

将“课程总结”§11“格式化输出”中的部分内容加入“chapter_8.doc”。

第八章输入输出流(input/outputstream)

8.1预定义类型的输入/输出

8.1.1基本情况及其优点

C++输入输出流的优点:

(一)重载运算符“<<”和“>>”能以函数重载的形式极大地扩大用途,在输入输出流中充分体现多态性。

C语言的输入/输出系统本来就灵活性大、功能比较完善。

但它有一个较大缺点:

无法处理众多的用户自定义数据类型(主要是类及其对象)。

例如,有一个结构类型exampl如下:

structexampl{

intj;

charstr[80];

}str_ex;

如欲输出此结构对象str_ex的两个成员的内容,因而笼统地使用如下输出语句printf,

printf(“%exampl”,str_ex);

则将会出现编译错误。

而C++的输出/输入系统则能很好地解决这个问题。

(二)类型安全(type-safe)

[例1]C语言输出语句中的类型错误(第一章已看过)

#include

voidmain()

{

inti=3;

doubled=4.4;

printf(“%d\t%f\n”,i,d);

}

运行结果:

34.400000对!

但如写错为:

printf(“%d\t%d\n”,i,d);

则编译时不出错,但运行结果错,为:

3-26214

但如写cout<

则得34.4,对!

始终不会出错!

(三)通过缓存增加功能。

(四)附带优点是书写方便以及显示中没有冗余字符,能自动略去尾数中的零(但如用户希望显示多余的零,也可以做到)。

C++的输入/输出系统是对流的操作,也即操作数据使其流向对象,或从对象流出。

什么是流?

流是从源头到目的的数据流动。

当键入字符时,字符从键盘流入程序中;当将数据写入磁盘文件中时,数据流动至磁盘上。

C++输入/输出流库是使用继承方法建立起来的一个输入/输出类库,它具有两个平行的基类,即streambuf类和ios类。

所有其它流类都是从它们直接或间接地派生出来的。

streambuf类用于提供物理设备的接口,它提供缓冲或处理流的通用方法。

它作为一个虚基类,具有类层次如下:

 

 

 

图8.1

ios类及其派生类用于为用户提供使用流类的接口。

它使用streambuf完成检查错误的格式化输入/输出操作,并支持对streambuf的缓冲区进行输入/输出时的格式化或非格式化转换。

ios类作为流库中的一个虚基类,派生出许多派生类,其主要层次如下:

 

 

 

 

 

 

 

图8.2

 

8.1.2预定义流(标准流)

预定义输出输入流涉及较多的头文件有四个:

ios.h,istream.h,ostream.h和iostream.h。

下面分别介绍。

8.1.2.1输出流

流输出运算符“<<”是在头文件ostream.h的classostream中定义的。

从图8.2可以看出,classostream是从classios中派生出来的。

因此下面先看一下用于定义classios的头文件ios.h。

先看ios.h:

/***

*ios.h-definitions/declarationsfortheiosclass.

***/

classios{

public:

enumio_state{goodbit=0x00,

eofbit=0x01,

failbit=0x02,

badbit=0x04};

enumopen_mode{in=0x01,

out=0x02,

ate=0x04,

app=0x08,

trunc=0x10,

nocreate=0x20,

noreplace=0x40,

binary=0x80};

enumseek_dir{beg=0,cur=1,end=2};

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};

staticconstlongbasefield;//dec|oct|hex

staticconstlongadjustfield;//left|right|internal

staticconstlongfloatfield;//scientific|fixed

ios(streambuf*);//differsfromANSI

virtual~ios();

inlinelongflags()const;

inlinelongflags(long_l);

inlinelongsetf(long_f,long_m);

inlinelongsetf(long_l);

inlinelongunsetf(long_l);

inlineintwidth()const;

inlineintwidth(int_i);

inlineostream*tie(ostream*_os);

inlineostream*tie()const;

inlinecharfill()const;

inlinecharfill(char_c);

inlineintprecision(int_i);

inlineintprecision()const;

……

//inlineoperatorvoid*()const;

operatorvoid*()const{if(state&(badbit|failbit))return0;return(void*)this;}

inlineintoperator!

()const;

……

protected:

ios();

ios(constios&);//treatasprivate

……

intstate;

longx_flags;

intx_precision;

charx_fill;

intx_width;

};

以后讨论到有关classios的问题时,可参照以上内容。

再看ostream.h:

/***

ostream.h-definitions/declarationsfortheostreamclass

***/

classostream:

virtualpublicios{

public:

ostream(streambuf*);

virtual~ostream();

ostream&flush();

…………

inlineostream&operator<<(ostream&(__cdecl*_f)(ostream&));

inlineostream&operator<<(ios&(__cdecl*_f)(ios&));

ostream&operator<<(constchar*);

inlineostream&operator<<(constunsignedchar*);

inlineostream&operator<<(constsignedchar*);

inlineostream&operator<<(char);

ostream&operator<<(unsignedchar);

inlineostream&operator<<(signedchar);

ostream&operator<<(short);

ostream&operator<<(unsignedshort);

ostream&operator<<(int);

ostream&operator<<(unsignedint);

ostream&operator<<(long);

ostream&operator<<(unsignedlong);

inlineostream&operator<<(float);

ostream&operator<<(double);

ostream&operator<<(longdouble);

ostream&operator<<(constvoid*);

ostream&operator<<(streambuf*);

inlineostream&put(char);

ostream&put(unsignedchar);

inlineostream&put(signedchar);

ostream&write(constchar*,int);

inlineostream&write(constunsignedchar*,int);

inlineostream&write(constsignedchar*,int);

ostream&seekp(streampos);

ostream&seekp(streamoff,ios:

:

seek_dir);

streampostellp();

protected:

ostream();

ostream(constostream&);//treatasprivate

ostream&operator=(streambuf*);//treatasprivate

ostream&operator=(constostream&_os){returnoperator=(_os.rdbuf());}

intdo_opfx(int);//notused

voiddo_osfx();//notused

private:

ostream(ios&);

ostream&writepad(constchar*,constchar*);

intx_floatused;

};

附注:

在C++的老版本中,_Cdecl是预定内部宏,供编译系统使用。

当它有定义(例如等于1)时,标示只选择C++语言而不选择Pascal语言。

而另一个宏_Pascal有定义时,则标示同时选择Pascal语言。

classostream_withassign:

publicostream{

public:

ostream_withassign();

ostream_withassign(streambuf*_is);

~ostream_withassign();

ostream&operator=(constostream&_os){returnostream:

:

operator=(_os.rdbuf());}

ostream&operator=(streambuf*_sb){returnostream:

:

operator=(_sb);}

};

externostream_withassigncout;

externostream_withassigncerr;

externostream_withassignclog;

从以上文件看出,classostream中所定义的各个流输出运算符“<<”是相对于各个预定义数据类型进行重载的。

也即,他们可用于各种预定义数据类型。

试看以下我们很熟悉的例子:

[例1]用于三种预定义数据类型的输出运算符

//out_1.cpp

//copiedfromp.341ofWang'sbook

#include

voidmain()

{

inti=10,j=45;

doublex=12.34,y=56.78;

char*str="Windows";

cout<<"i="<

cout<<"x="<

cout<<"str="<

}

/*Results:

i=10,j=45

x=12.34,y=56.78

str=Windows

*/

在以上程序中,流输出运算符采用左结合方式,允许将多个输出运算操作组合到一个语句中。

不同类型的数据也可组合到一条语句中。

8.1.2.2缓冲与非缓冲输出流

从图8.2和ostream.h中可看出,从classostream中派生出classostream-withassign,而ostream-withassign建立了三个对象:

cout、cerr和clog。

这就是标准库中定义的三个输出流。

其中cout是标准的输出流,而cerr和clog则与标准错误流相关。

其中,cout和cerr是非缓冲输出流,发送给它们的任何数据都立即输出;而clog是缓冲输出(bufferedoutput)流。

在缓冲输出流中,只当满足以下四个条件中之一时,缓存才把所存数据向文件(即标准输出设备,缺省为显示终端屏幕)输出:

(1)第一个条件:

调用flush函数:

前面看到,flush函数是classostream的成员函数。

此处它用于将输出流刷新,从而将流缓冲区的内容输出到与流相关的输出设备中。

[例1]//i_o_1_1.cpp//Touseflushfunctiontodisplayoutput#includevoidmain(){inti=12345;clog<<"ABCDE";cout<

clog<

}

/*Results:

12345

ABCDE*/

[例2]//i_o_1_2.cpp#includevoidmain(){inti=12345;clog<<"ABCDE"<

ABCDE12345*/

注意:

cout调用flush无意义,因它是非缓冲输出流

(2)第二个条件:

程序结束:

[例3]//i_o_2.cpp

//Dataaredisplayedwhentheprogramterminates

#include

voidmain()

{

inti=12345;

clog<<"ABCDE";

cout<

}

/*Results:

12345

ABCDE*/

其实,程序结束时clog自动调用了flush函数,所以这个程序与i_o_1_1.cpp完全相同!

(3)第三个条件:

缓存满(一般为512个字节)后自动将数据输出至文件(如显示屏),并清除缓存,准备接收其它数据:

[例4]//i_o_4.cpp//textisdisplayedwhenthebufferisfull#includevoidmain(){inti=12345;

for(intc=0;c<33;c++)

clog<<"ABCDEFGHIJKLMNOP";

//totally16characterscout<

sixrows(80characterseach)plus32

characters,totally512charactersdisplayed12345ABCDEFGHIJKLMNOP

(duetoprogramtermianation)*/

(4)第四个条件:

clog自己调用endl符,但不是”\n”:

[例5]//i_o_3_1.cpp

//Todisplaybyusingendl

#include

voidmain()

{

inti=12345;

clog<<"ABCDE"<

cout<

}

/*Results:

ABCDE

12345*/

[例6]//i_o_3_2.cpp//clogbutnotcoutdisplaystextby

//using“endl”#include

voidmain()

{

inti=12345;

clog<<"ABCDE";

cout<

clog<

}

/*Results:

[CR]

12345ABCDE*/

当程序中同时出现clog和cout语句而clog和cout的语句中都是既无“flush”又无“endl”时,规则较为复杂,请参阅附录二十一。

8.1.2.3缓冲输入流

流输入运算符“>>”是在头文件istream.h的classistream中定义的。

classistream也是从classios中派生出来的。

因此下面看一下用于定义classistream的头文件istream.h。

又看istream.h:

/***

istream.h-definitions/declarationsfortheistreamclass

***/

classistream:

virtualpublicios{

public:

istream(streambuf*);

virtual~istream();

inlineistream&operator>>(istream&(__cdecl*_f)(istream&));

inlineistream&operator>>(ios&(__cdecl*_f)(ios&));

istream&operator>>(char*);

inlineistream&operator>>(unsignedchar*);

inlineistream&operator>>(signedchar*);

istream&operator>>(char&);

inlineistream&operator>>(unsignedchar&);

inlineistream&operator>>(signedchar&);

istream&operator>>(short&);

istream&operator>>(unsignedshort&);

istream&operator>>(int&);

istream&operator>>(unsignedint&);

istream&operator>>(long&);

istream&operator>>(unsignedlong&);

istream&operator>>(float&);

istream&operator>>(double&);

istream&operator>>(longdouble&);

istream&operator>>(streambuf*);

intget();

inlineistream&get(char*,int,char='\n');

inlineistream&get(unsignedchar*,int,char='\n');

inlineistream&get(signedchar*,int,char='\n');

istream&get(char&);

inlineistream&get(unsignedchar&);

inlineistream&get(signedchar&);

istream&get(streambuf&,char='\n');

inlineistream&getline(char*,int,char='\n');

inlineistream&getline(unsignedchar*,int,char='\n');

inlineistream&getline(signedchar*,int,char='\n');

inlineistream&ignore(int=1,int=EOF);

istream&read(char*,int);

inlineistream&read(unsignedchar*,int);

inlineistream&read(signedchar*,int);

intgcount()const{returnx_gcount;}

intpeek();

istream&putback(char);

intsync();

istream&seekg(streampos);

istream&seekg(streamoff,ios:

:

seek_dir);

streampostellg();

voideatwhite();

protected:

istream();

istream(constistream&);//treatasprivate

istream&operator=(streambuf*_isb);//treatasprivate

istream&operator=(constistream&_is){returnoperator=(_is.rdbuf());}

istream&get(char*,int,int);

intdo_ipfx(int);

private:

istream(ios&);

intgetint(char*);

intgetdouble(char*,int);

int_fGline;

intx_gcount;

};

classistream_withassign:

publicistream{

publ

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 初中教育

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1