chapter7-C++的IO流.doc_第1页
chapter7-C++的IO流.doc_第2页
chapter7-C++的IO流.doc_第3页
chapter7-C++的IO流.doc_第4页
chapter7-C++的IO流.doc_第5页
已阅读5页,还剩41页未读 继续免费阅读

下载本文档

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

文档简介

第八章输入输出流(inputoutput stream)的基本概念及原理8.1预定义数据类型的输入输出8.1.1基本情况及其优点C+输入输出流的优点:(一)重载运算符“”能以函数重载的形式极大地扩大用途,在输入输出流中充分体现多态性。C语言的输入输出系统本来就灵活性大、功能比较完善。但它有一个较大缺点:无法处理众多的用户自定义数据类型(主要是结构体、类及其对象)。例如,有一个结构体类型exampl如下:struct exampl int j;char str80; str_ex;如欲输出此结构体对象str_ex的两个成员的内容,因而笼统地使用如下输出语句printf,printf(“%exampl”, str_ex);则将会出现编译错误。而C+的输出/输入系统则能很好地解决这个问题。(二)类型安全(type-safe)例1C语言输出语句中的类型错误(第一章已看过)include void main( )int i=3;double d=4.4;printf(“%dt%fn”, i, d);运行结果:34.400000对!但如写错为:printf(“%dt%dn”, i, d);则编译时不出错,但运行结果错,为:3 26214但在C+中只须写couti“”dendl;而不必写出变量类型!就能得出34.4,对!始终不会出错!(三)通过缓存增加功能。(四)附带优点是书写方便以及显示中没有冗余字符,能自动略去浮点数尾数中的零(但如用户希望显示多余的零,也可显示)。C+的输入输出系统是对流的操作,也即操作数据使其流向对象,或从对象流出。什么是流?流是从源头到目的的数据流动。当键入字符时,字符从键盘流入程序中;当将数据写入磁盘文件中时,数据自程序流动至磁盘上。C+输入输出流库是使用继承方法建立起来的一个输入输出类库,它具有两个平行的基类,即streambuf类和ios类。所有其它流类都是从它们直接或间接地派生出来的。streambuf类用于提供物理设备的接口,它提供缓冲或处理流的通用方法。它作为一个虚基类,具有类层次如下:streambufconbuffilebufstrstreambuf图 8.1ios类及其派生类用于为用户提供使用流类的接口。它使用streambuf完成检查错误的格式化输入输出操作,并支持对streambuf的缓冲区进行输入输出时的格式化或非格式化转换。ios类作为流库中的一个虚基类,派生出许多派生类,其主要层次如下:i o sistreamfstreambaseostreamfstreamistream-withassignostream-withassigniostreamiostream-withassign图 8.28.1.2 预定义流(标准流)的基本原理预定义输出输入流涉及较多的头文件有四个:ios.h,istream.h,ostream.h和iostream.h。下面分别介绍。8.1.2.1 输出流的基本概念输出流运算符“”是在头文件ostream.h的class ostream中定义的。从图8.2可以看出,class ostream是从class ios中派生出来的。因此下面先看一下用于定义class ios的头文件ios.h。先看ios.h:/*ios.h - definitions/declarations for the ios class.*/#ifndef NULL#define NULL 0#endif#ifndef EOF#define EOF (-1)#endifclass ios public: enum io_state goodbit = 0x00, eofbit = 0x01, failbit = 0x02, badbit = 0x04 ;(输出输入操作结果的状态) enum open_mode in = 0x01, out = 0x02, ate = 0x04, app = 0x08, trunc = 0x10, nocreate = 0x20, noreplace = 0x40, binary = 0x80 ; enum seek_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 ; static const long basefield; / dec | oct | hex(不同基数制) static const long adjustfield; / left | right | internal(对齐方式) static const long floatfield; / scientific | fixed(浮点数显示格式) ios(streambuf*); / differs from ANSI virtual ios(); inline long flags() const; inline long flags(long _l); inline long setf(long _f,long _m); inline long setf(long _l); inline long unsetf(long _l); inline int width() const; inline int width(int _i); inline ostream* tie(ostream* _os); inline ostream* tie() const; inline char fill() const; inline char fill(char _c); inline int precision(int _i);inline int precision() const;/ inline operator void*() const; operator void *() const if(state&(badbit|failbit) ) return 0; return (void *)this; inline int operator!() const;protected: ios(); ios(const ios&); / treat as private int state;long x_flags; int x_precision; char x_fill; int x_width;以后讨论到有关class ios的问题时,可参照以上内容。再看ostream.h:/*ostream.h - definitions/declarations for the ostream class*/class ostream : virtual public ios public: ostream(streambuf*); virtual ostream(); ostream& flush(); ostream& endl();inline ostream& operator(ostream& (_cdecl * _f)(ostream&);inline ostream& operator(ios& (_cdecl * _f)(ios&); ostream& operator(const char *);inline ostream& operator(const unsigned char *);inline ostream& operator(const signed char *);inline ostream& operator(char); ostream& operator(unsigned char);inline ostream& operator(signed char); ostream& operator(short); ostream& operator(unsigned short); ostream& operator(int); ostream& operator(unsigned int); ostream& operator(long); ostream& operator(unsigned long);inline ostream& operator(float); ostream& operator(double); ostream& operator(long double); ostream& operator(const void *); ostream& operator(streambuf*);inline ostream& put(char); ostream& put(unsigned char);inline ostream& put(signed char); ostream& write(const char *,int);inline ostream& write(const unsigned char *,int);inline ostream& write(const signed char *,int); ostream& seekp(streampos); ostream& seekp(streamoff,ios:seek_dir); streampos tellp();protected: ostream(); ostream(const ostream&); / treat as private ostream& operator=(streambuf*); / treat as private ostream& operator=(const ostream& _os) return operator=(_os.rdbuf(); int do_opfx(int); / not used void do_osfx(); / not usedprivate: ostream(ios&); ostream& writepad(const char *, const char *); int x_floatused;附注:以上函数原型声明中,常出现_Cdecl一词。它是函数调用约定,是C和C+程序的默认调用方式,又称为C调用约定。允许函数的实参数目变动。详见第二章2.8.6“函数的调用约定”。class ostream_withassign : public ostream public: ostream_withassign(); ostream_withassign(streambuf* _is); ostream_withassign(); ostream& operator=(const ostream& _os) return ostream:operator=(_os.rdbuf(); ostream& operator=(streambuf* _sb) return ostream:operator=(_sb); ;extern ostream_withassign cout;extern ostream_withassign cerr;extern ostream_withassign clog;从以上文件看出,class ostream中所定义的19个重载的输出流运算符“”是相对于各个预定义数据类型进行重载的。也即,他们可用于各种预定义数据类型。此外,本章中常用的cout、cerr和clog都是class ostream_withassign的对象。 试看以下我们很熟悉的例子:例1用于三种最常用预定义数据类型的输出运算符/ out_1.cpp#include void main( )int i=10, j=45;double x=12.34, y=56.78;char * str=Windows;couti=i,j=jendl;coutx=x,y=yendl;coutstr=strendl;/* Results:i=10,j=45x=12.34,y=56.78str=Windows*/在以上程序中,输出流对象cout顺序地调用各种重载的输出流运算符”,将一条语句中的多个不同类型的数据依次输出。输出流对象cout还可用于输出各类函数的运行结果,如下例:例2输出各类函数的运行结果/ out_2.cpp#include int fun1( )int j = 111;return j;double fun2( )double j = 13.57;return j;void main()coutThe first fun has fun1( ); the second fun has fun2( )endl;/* Results:The first fun has 111; the second fun has 13.57*/从图8.2和ostream.h中可看出,从class ostream中派生出class ostream-withassign,而ostream-withassign建立了三个对象:cout、clog和cerr。这就是标准库中定义的三个输出流对象。其中cout是标准的输出流对象,而cerr和clog则与标准错误流有关,但它们也可用作普通输出流对象。其中,cout和clog是缓冲输出流(buffered output stream)对象,发送给它们的数据暂存在缓存内,只当满足8.1.2.3中所述条件之一时才将数据输出至标准输出设备;而cerr是非缓冲输出流对象, 发送给它的任何数据在执行完一条语句后立即输出。现在简要地看一下输出流对象cout、clog和cerr级联地运行的过程。从以上图8.2和ostream.h中可看出:cout、clog和cerr都是class ostream-withassign的对象,而class ostream-withassign是从class ostream中派生出来的,因此class ostream是这些输出流对象的基类。以cout为例,这是对象cout调用函数operator ( ),也即cout.operator ( )。按照支配规则,也即对象cout调用了基类的成员函数operator ( )。函数operator ( )原型的返回值是其基类class ostream对象的引用,而实际上则返回class ostream的派生类class ostream-withassign的对象cout的引用。此返回的对象可继续调用下一个函数operator ( )。直至整条语句末尾。如只从表面看,有些现象看不清楚,见以下数例:例1变量值自增后输出有错/ out_10.cpp/ trap of cout statement#include void main( )int i=10;coutfirst i=i,second i=+iendl;/* Results:first i=11,second i=11*/以上程序中,原来指望first i=10,结果不然。似乎一开始i就自增了。以后将分析这点。例2 变量值自增后输出有错又一例/ out_12.cpp/ trap of cout statement#include void main( )int i=10;coutfirst i=+i,second i=iendl;/* Results:first i=11,second i=10*/结果又和预期值不符合。为何?怪现象还有:例3第七章7.1“程序运行错误及其处理”中例1程序sqrt_negative_1.cpp。该程序中主函数第二语句“coutSqrt of -4 is sqroot(-4)endl;”出错,但并不显示字符串“Sqrt of -4 is”。例4有些输出语句并不立即输出数据。/ out_4.cpp/ To use endl( ) function to display output contents#include #include / for getch()void main()char *c12=12345 ;coutc12ABCD c12;getch();coutABCDEFGendl;/* Results:只在击键一次之后,才能显示以下内容:12345 ABCD 12345 ABCDEFG*/以上程序中,主函数的第二语句运行完后,并无输出,也即屏幕上并无显示。何故?这些都只能从汇编语言的更深层次来解释。(补充说明:在较新版本例如VS2008中,例2和例4的问题已经解决)整句cout、clog或cerr输出语句的运行都可分为三个阶段:入栈阶段、缓存阶段和输出阶段。详述如下。第一阶段 - 入栈阶段此阶段由主函数main( ) 在编译过程中完成。主函数按照逆顺序将整条输出语句中需要输出的各项数据或数据的存放地址压入栈区。其中:(a) 如果数据是单个数据(无论预定义类型或是用户自定义类型),则直接将该项数据压入栈区。其中整型数据或单个字符占4个字节(堆栈按照4字节边界原则运行,4-byte boundary,即小于4字节者也按4字节分配空间),double型数据占8个字节,类的对象则可能占更多空间,等等。(b)如果数据是数组,则系统将该数组放置于数据区内,并将此数组首址压入栈区。(c)如果数据是一个函数运行后的返回值,则系统执行该函数,并根据该函数返回值的数值类型,按照上两项规定来决定将该数据或是数据地址压入栈区。其所以要逆向入栈,是为了在以下阶段中能够首先从栈中获得排在输出语句前面的数据或数据地址。以下面最简单输出语句为例:/ out_12.cpp#include void main( )int i=10;couti,+iendl;/* Results:11,11*/此程序的运行结果和预料的不同。本来希望结果是10和11的。其原因在于入栈阶段中第二个i经过自增操作了。试看下图:Table_out_1:程序out_12.cpp入栈阶段后的栈区内容11( 第一个 i,数值与第二个i相同)44(2Ch,,的ASCII码值)11( 第二个 i,前置自增,成为11)0x0040100f(函数endl地址)低地址高地址由于数据压入栈区的顺序是从输出语句的末端开始的,因此首先压入函数endl地址;再压入第二个前置自增后的i值,即11;接着压入,的ASCII码值;最后压入第一个 i的值,仍为11。为解决程序out_12.cpp中的问题,可将输出语句分两行书写,如下面程序:例5 / out_11.cpp/ correct use of cout statement#include void main( )int i=10;cout第一个 i = i;cout,第二个 i = +iendl;/* Results:第一个 i = 10,第二个 i = 11*/第二阶段 - 缓存阶段此阶段在程序运行过程中由重载运算符函数“”完成。它取出栈区内所存数据或按数据地址找到数据本身,并将该项完整的数据存入位于堆区内的缓存。如缓存是空的,则该数据被放置于缓存的首址(例如8.1.2.2“非缓冲输出流” );如缓存内已存有其它数据,则该数据被放置于缓存内已有数据之后(例如8.1.2.3“缓冲输出流” )。缓存长度的缺省值一般为512个字节。第三阶段 - 输出阶段此阶段由另一些重载运算符函数“”调用flush函数来完成,它们最终调用硬件接口的函数_imp_WriteFile,直接将数据输出至标准输出设备(显示屏幕)。由于函数_imp_WriteFile无法访问堆区,因此必须再将数据从堆区内再转存至栈区内,才能供函数_imp_WriteFile调用后输出。flush函数顺序地从缓存(堆区)内取出所存全部数据,从新压入至栈区另外的地址,以备输出。接着函数_imp_WriteFile直接将位于栈区新地址处的全部数据输出至标准输出设备(显示屏幕)。入栈阶段 缓存阶段 输出阶段主函数main( )按照逆顺序将整条输出语句中需要输出的各项数据或数据的存放地址压入栈区。重载运算符函数“”顺序地取出栈区内所存数据或按数据地址找到数据本身,并将该项完整的数据存入位于堆区内的缓存。另一些重载运算符函数“”调用flush函数,最终调用硬件接口函数_imp_WriteFile,直接将数据输出至标准输出设备(显示屏幕)。第一阶段入栈阶段栈区主函数内栈区各数据或数据地址存入堆栈(第一个数据或其地址在栈上低地址处)输出语句(如cout语句等)中待输出的各数据按逆向顺序入栈第二阶段缓存阶段栈区堆区各数据或数据地址存入堆栈(第一个数据或其地址在栈上低地址处)顺序排列的全部完整数据将全部完整数据顺序地自栈区移入堆区第三阶段输出阶段输出设备 栈区 堆区各数据或数据地址存入堆栈(第一个数据或其地址在栈上低地址处)标准输出设备(屏幕)顺序排列的全部完整数据将全部完整数据顺序地输出将全部完整数据顺序地自堆区移入另外栈区下面将分别介绍缓冲输出流对象(cout或clog)和非缓冲输出流对象(cerr),它们在执行输出语句时的差别在于:(1)每当非缓冲输出流对象cerr语句运行时,在入栈阶段之后,它调用重载运算符函数“”,接连地执行缓存阶段和输出阶段,直接将全部数据输出至标准输出设备(显示屏幕)。(2)每当缓冲输出流对象cout或clog语句运行时,一般情况下只执行入栈阶段和缓存阶段,只将数据存入缓存而不输出数据。只当满足8.1.2.3中所述条件之一时才执行输出阶段的操作,通过运算符函数“”,从堆区中的缓存内取出所存全部数据,调用用于控制硬件接口的函数_imp_WriteFile,直接将全部数据输出至标准输出设备(显示屏幕)。8.1.2.2非缓冲输出流的运行机理cerr是非缓冲输出流对象,发送给它的所有数据在整条输出语句(不是半条语句或大半条语句)运行后立即输出至标准输出设备。例1非缓冲输出流对象cerr一次将整条语句的数据顺序地输出至标准输出设备。/ out_3.cpp/ cerr outputs the contents of one statement immediately#include int fun1( )int j = 512;return j;double fun2( )double j = 12.34;return j;void main()cerrThe first result is fun1( );the second result is fun2( );/* Results:The first result is 512;the second result is 12.34*/以上程序out_3.cpp中只有一句cerr输出语句,整个语句的运行分为两大步骤:第一大步骤就是入栈阶段;第二大步骤包括缓存阶段和输出阶段。第一大步骤 - 入栈阶段主函数按照逆顺序将整条语句中需要输出的各项数据或数据的存放地址压入栈区。其顺序操作如下:(a) 系统执行函数fun2( ),其运行结果为12.34。此数据被压入栈区,占8个字节。(b)第二项被压入栈区的数据是字符串the second result is 在数据区内的地址(0042a038)。(c)第三项被压入栈区的数据是字符;(其ASCII码值为3Bh),占4个字节。(d)系统接着执行函数fun1( ),其运行结果512被压入栈区,占4个字节。(e)第五项也即最后一项被压入栈区的数据是字符串the first result is 在数据区内的地址(0042a01c)。Table_out_2:程序out_3.cpp入栈阶段后的栈区内容0x0042a01c512;(3Bh)0x0042a03812.34低地址高地址请注意:以上数据压入栈区的顺序是从输出语句的末端开始的。第二大步骤:缓存阶段和输出阶段非缓冲输出流对象cerr是逐个地输出数据的。对于每个数据,非缓冲输出流对象cerr都调用运算符函数,并一气呵成地完成数据缓存和输出的操作,直接将该项数据输出至标准输出设备(显示屏幕)。其详细过程请参阅附录二十六“非缓冲输出流对象cerr输出数据的详细过程”。由以上可见,在入栈阶段中要求所有函数fun1( )和fun2( )都正常运行,并返回运行结果,然后才能进入第二和第三阶段。如果程序运行发生意外而导致程序中断,则整条输出语句的数据将没有一项能够输出或显示。由于这个原因,第七章的多个程序中,当主函数的语句运行过程中抛出异常因而导致程序意外中断时,整条语句的所有数据都不能显示。请比较下节中例6和例7的运行结果。8.1.2.3缓冲输出流的运行机理在缓冲输出流中,只当满足以下四个条件中之一时,系统才把所存数据从缓存输出至标准输出设备(缺省设备为显示终端的屏幕):(1)第一个条件:调用endl或flush函数:前面看到,flush和endl函数都是class ostream的成员函数。两者的区别在于:flush函数用于将输出流缓存刷新,从而将缓存中的内容输出到与流相关的输出设备中。而endl函数则调用了flush函数,除将输出流刷新外,还执行回车操作。例1调用endl函数以便刷新缓存/ out_4.cpp/ To use endl( ) function to display output contents#include #include / for getch()void main()char *c12=12345 ;coutc12ABCD c12;getch();coutABCDEFGendl;/* Results:只在击键一次之后,才能显示以下内容:12345 ABCD 12345 ABCDEFG(这说明在调用endl函数之前,cout语句不输出任何数据)*/在out_4.cpp的例子中,共有两条cout语句。其处理流程为:第一条cout语句不调用endl函数,只执行前两个阶段,即入栈阶段和缓存阶段;第二条cout语句调用endl函数,除执行前两个阶段外,还执行输出阶段。(一) 入栈阶段和缓存阶段 - 在out_4.cpp的例子中:(a)先处理第一条cout语句。主函数按照逆顺序将整条语句中需要输出的三项数据的存放地址压入栈区,如下:Table_out_3:out_4.cpp第一条cout语句入栈阶段后的栈区内容0x0042a024(字符串“12345 ”地址)0x0042a038(字符串“ABCD ”地址)0x0042a024(字符串“12345 ”地址)低地址高地址然后由输出流对象cout调用重载运算符函数,顺序地分别按照栈区内的地址取出数据区内第一至第三项数据即字符串12345 、字符串ABCD 和字符串12345 ,并按顺序存入缓存内(位于堆区内,其首址例如为p=0x00441810)。(b)接着处理第二条cout语句。除执行入栈阶段和缓存阶段外,还执行输出阶段。首先执行入栈阶段和缓存阶段,主函数继续按照逆顺序将整条语句中需要输出的各项数据或数据的存放地址压入栈区。Table_out_4:out_4.cpp第二条cout语句入栈阶段后的栈区内容0x0042a01c(字符串ABCDEFG地址)0x0040101e(函数endl的地址)低地址高地址接着输出流对象cout调用重载运算符函数,按照栈区内的地址取出数据区内第四项数据即字符串ABCDEFG,存入缓存内已有的第三项数据之后。(二)输出阶段:由于栈区内最后一个所存数据是函数endl的地址 (0040101e),重载运算符函数按此地址调用该函数。从而执行第三阶段即输出阶段。系统顺序地从缓存内(位于堆区内,其首址例如为p=0x00441810)取出所存全部数据,并将其全部压入栈区一定地址(在out_4.cpp程序中其首址例如在lfbuf=0x0012f97c处),以供函数_imp_WriteFile调用输出。其详细过程请参阅附录二十七“缓冲输出流对象调用endl函数的详细过程”。上例的第二条cout语句中,如用flush函数替代endl函数,或者用clog替代cout,程序的运行结果将完全相同。(2)第二个条件:程序结束: 例2在程序结束之前,clog不输出任何数据/ out_5.cpp/ To display output contents at the end of the program#include #include / for getch()void main()char *c12=12345 ;clogABCD c12ABCDEFG ;clogc12;getch();/* Results:只在击键一次之后,才能显示以下内容:ABCD 12345 ABCDEFG 12345(这说明在程序结束之前,clog语句不输出任何数据)*/在以上程序out_5.cpp的数据输出阶段中,函数main( )结束时,程序返回至系统函数mainCRTStartup( )内(系统是由此进入函数main( )的),并在此函数中调用函数exit( )。然后几经周折,调用函数_write。系统取出堆区内所存全部数据(out_5.cpp例中首址例如在p=0x00441810),并将其全部压入栈区一定地址(out_5.cpp例中其首址例如在lfbuf=0x0012fadc处),以供函数_imp_WriteFile输出,直接将所有数据输出至标准输出设备(显示屏幕)。(3)第三个条件:当出现cerr语句或cin语句时:例3在执行非缓冲输出流对象cerr语句前,cout不输出任何数据/ out_6.cpp/ No display of cout statement before executing cerr statement#include #include void main()char *c12=12345 ;cerrABCDEFG ;coutc12;getch();cerrABCD ;coutc12endl;/调用endl函数,显示c12/* Results:ABCDEFG (击键一次后继续显示)12345 ABCD 12345*/整个out_6.cpp程序包括四条输出语句:两条cerr语句(非缓冲输出流对象)和两条cout语句(缓冲输出流对象)。程序第一条输出语句是cerr语句。整句cerr输出语句的运行如同8.1.2.2“非缓冲输出流”例1中程序out_3.cpp一样,执行完整条语句后随即显示数据。程序第二条输出语句是cout语句。整句cout输出语句的执行过程只有入栈阶段和缓存阶段而没有输出阶段,结果只是分别将字符串12345 存入缓存(首址例如在0x00431570)内。程序第三条输出语句是cerr语句。整句cerr输出语句的运行分为三个阶段:在入栈阶段中,主函数先将数据(字符串ABCD )的地址压入栈区;在进入缓存阶段之前,非缓冲输出流对象cerr通过重载运算符函数调用flush函数,先将缓存清空,因而将缓存内全部数据(字符串12345 )转存至栈区,通过函数_imp_WriteFile将数据输出至标准输出设备(显示屏幕),其结果是显示字符串12345 。接着进入正常的缓存和输出阶段,其操作和本程序中第一条cerr语句相同,其结果是显示字符串ABCD 。程序第四条输出语句是cout语句。由于调用endl函数,整句cout输出语句的执行过程完整地包括入栈阶段、缓存阶段和输出阶段,结果是将字符串12345 输出至标准输出设备。例4在执行输入流对象cin语句前,cout不输出任何数据/ out_13.cpp/ No display of cout statement before executing cin statement#include void main()int data;coutdata;coutdataendl;/显示整型数据值/* Results:ABCDEFG (用户输入整型数据及回车符)123123 (cout语句再次显示该数据值)*/以上程序中,执行第一条cout语句时,只完成入栈阶段和缓存阶段而没有输出阶段,接着执行cin语句,此时输出字符串ABCDEFG 。待用户输入整型数据例如123并回车符后,第二条cout语句再次显示该数据值123。(4)第四个条件:缓存溢出(缓存长度缺省值为512个字节)后自动将数据输出至标准输出设备,并清除缓存,准备接收其它数据:例5 512个字节的缓存满后自动将数据输出至显示屏,并清除缓存/ out_7.cpp/ texts are displayed when the data overflow the buffer#include #include /for getch( )void main()for (int c=0; c8; c+)coutABCDEFGHIJKLMNOPQRSTUVWXYZZYXWVUABCDEFGHIJKLMNOPQRSTUVWXYZZYXWVU;/ totally 64*8 = 512 charactersgetch( );cout&;getch( );cout12345;/* Results:(第一条cout循环语句共有512个字符,正好是一个缓存的长度,但缓存虽满,尚未溢出,故不刷新,也不输出数据。必须继续存入数据(此处继续存入一个回车符),使缓存溢出后,方能刷新缓存,因此必须击键一次后方能显示以下512个字符)ABCDEFGHIJKLMNOPQRSTUVWXYZZYXWVUABCDEFGHIJKLMNOPQRSTUVWXYZZYXWVUABCDEFGHIJKLMNOPQRSTUVWXYZZYXWVUABCDEFGHIJKLMNOPQRSTUVWXYZZYXWVUABCDEFGHIJKLMNOPQRSTUVWXYZZYXWVUABCDEFGHIJKLMNOPQRSTUVWXYZZYXWVUABCDEFGHIJKLMNOPQRSTUVWXYZZYXWVUABCDEFGHIJKLMNOPQRSTUVWXYZZYXWVUABCDEFGHIJKLMNOPQRSTUVWXYZZYXWVUABCDEFGHIJKLMNOPQRSTUVWXYZZYXWVUABCDEFGHIJKLMNOPQRSTUVWXYZZYXWVUABCDEFGHIJKLMNOPQRSTUVWXYZZYXWVUABCDEFGHIJKLMNOPQRSTUVWXYZZYXWVUABCDEFGHIJKLMNOPQRSTUVWXYZZYXWVUABCDEFGHIJKLMNOPQRSTUVWXYZZYXWVUABCDEFGHIJKLMNOPQRSTUVWXYZZYXWVU(又击键一次后再次显示:)&12345*/在以上程序out_7.cpp中,当缓存刚好充满时,运算符函数并不将缓存(首址例如为0x00441880)刷新。只当继续存入数据(此处为字符&),使缓存溢出时,运算符函数才将缓存(首址例如为0x00441880)刷新。也即将堆区内地址例如0x00441880处所存全部数据(共512个字节)复制至栈区(例如lfbuf=0x0012f920)处,然后随即输出至标准输出设备(显示屏幕),显示512个字符。而字符&则在第二阶段结束时

温馨提示

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

评论

0/150

提交评论