C语言的I∕O流类库.ppt

上传人:s9****2 文档编号:568661528 上传时间:2024-07-25 格式:PPT 页数:65 大小:264.05KB
返回 下载 相关 举报
C语言的I∕O流类库.ppt_第1页
第1页 / 共65页
C语言的I∕O流类库.ppt_第2页
第2页 / 共65页
C语言的I∕O流类库.ppt_第3页
第3页 / 共65页
C语言的I∕O流类库.ppt_第4页
第4页 / 共65页
C语言的I∕O流类库.ppt_第5页
第5页 / 共65页
点击查看更多>>
资源描述

《C语言的I∕O流类库.ppt》由会员分享,可在线阅读,更多相关《C语言的I∕O流类库.ppt(65页珍藏版)》请在金锄头文库上搜索。

1、第第11章章 C+语言的语言的I/O流类库流类库本本章章的的最最主主要要目目的的就就是是把把对对象象保保存存到到磁磁盘盘文文件件中中并并从从磁磁盘盘文文件件重重建建对对象象。当当然然C+可可完完成成更更多多的任务。的任务。C+语言中并没有输入语言中并没有输入/输出语句,而是在输出语句,而是在标准库里包含了一个标准库里包含了一个I/O流类库,它与标准模板流类库,它与标准模板库同为库同为C+标准库中最重要的组成部分。数据从标准库中最重要的组成部分。数据从一个对象到另一个对象的传送被抽象为一个对象到另一个对象的传送被抽象为“流流”。数据的输入数据的输入/输出就是通过输入输出就是通过输入/输出流来实现

2、的。输出流来实现的。 流是一种抽象的概念,负责在数据的产生者流是一种抽象的概念,负责在数据的产生者和数据的使用者之间建立联系,并管理数据的流和数据的使用者之间建立联系,并管理数据的流动。动。 第第11章章 C+语言的语言的I/O流类库流类库11.1 I/O流类库的功能流类库的功能 11.3 格式化输入输出格式化输入输出操作操作11.2 常用的读写操作常用的读写操作11.4 插入符和提取符插入符和提取符的重载的重载 11.7 流错误处理流错误处理 11.5 磁盘文件的输入磁盘文件的输入和输出操作和输出操作下 课11.6 字符串流操作字符串流操作 11.1 I/O流类库的功能流类库的功能整个流类体

3、系是一个派生类体系。整个流类体系是一个派生类体系。按按ANSI C+标准,类标准,类ios是抽象类,它的析构函数是虚函数,它是抽象类,它的析构函数是虚函数,它的构造函数为保护的,作为所有基本流类的基类。的构造函数为保护的,作为所有基本流类的基类。VC+中有一个构造函数中有一个构造函数ios (streambuf*)为公有,为公有,与与ANSI C+不同。不同。iosstreambufistreamostreamistream_withassigniostreamostream_withassigniostream_withassign指针指针11.1 I/O流类库的功能流类库的功能11.1.1

4、 基本的基本的I/O流类库流类库在流类库中,最重要的两部分功能为在流类库中,最重要的两部分功能为标准输入标准输入/ /输出输出(standard input/outputstandard input/output)和和文件处理文件处理。 在在C+C+的流类库中定义了四个全局流对象:的流类库中定义了四个全局流对象:cincin,coutcout,cerrcerr和和clogclog。可以完成人机交互的功能。可以完成人机交互的功能。 cin标准输入流对象,键盘为其对应的标准设备。标准输入流对象,键盘为其对应的标准设备。 cout标准输出流对象,显示器为标准设备。标准输出流对象,显示器为标准设备。

5、cerr和和clog标准错误输出流,输出设备是显示器。标准错误输出流,输出设备是显示器。 其中其中cin、cout和和clog是带缓冲区的,缓冲区由是带缓冲区的,缓冲区由streambuf类对象来管理。而类对象来管理。而cerr为非缓冲区流,一旦为非缓冲区流,一旦错误发生立即显示。错误发生立即显示。 要使用这四个功能,必须包含要使用这四个功能,必须包含文件。文件。 11.1.2 文件I/O操作流类库类ifstream由类istream单一派生,专门用来处理文件的输入操作。类ofstream由类ostream单一派生,专门用来处理文件的输出操作。类fstream由类iostream单一派生,专门

6、用来处理文件的输入和输出操作。类ifstream、ofstream、fstream拥有公共基类: fstreambase。利用上述类创建流对象,类中的成员函数open用来打开文件,成员函数close用来关闭文件,有关细节将在11.5节中讲述。11.1.3 字符串流操作流类库类istrstream由类istream单一派生,专门用来处理字符串的输入操作。类ostrstream由类ostream单一派生,专门用来处理字符串的输出操作。类strstream由类iostream单一派生,专门用来处理字符串的输入和输出操作。类istrstream、ostrstream、strstream拥有公共基类:

7、strstreambase。有关字符串流操作的细节将在11.6节中讲述。11.2 常用的读写操作n11.2.1 屏幕输出操作n1.使用预定义的插入符n是左移位运算符的重载,格式为:是左移位运算符的重载,格式为:n字符流目的地字符流目的地字符流内容字符流内容n需在屏幕显示时,屏幕就是字符流目的地,头文件iostream.h中定义有ostream类的全局对象cout就代表屏幕。n使用时应注意运算符的优先级别,必要时,用加括弧的方法保证其他运算符优先运算,例如:ncoutj?i:j)endl;n如果不加(),将因运算顺序不对而编译出错。【例例11.1】插入符用法示例插入符用法示例#include#i

8、ncludevoid main( ) cout字符串字符串This is a string.的长度为:的长度为:; coutstrlen(This is a string.)endl; cout字符串字符串This is a string.占的空间为:占的空间为:; coutsizeof(This is a string.)endl;运行结果为运行结果为17和和18,因为因为strlen是求字符串的长度,即字是求字符串的长度,即字符串中字符的个数;符串中字符的个数;sizeof是求占用内存的字节数,是求占用内存的字节数,其中包括字符串结束标志空字符占用的内存。其中包括字符串结束标志空字符占用的

9、内存。strlen在在string.h中定义,中定义,sizeof是一个运算符。是一个运算符。【例11.2】输出变量地址值示例#includevoid main( ) int x(100); int *px=&x; coutx=xn十进制&x=long(&x)endl; cout*px=*pxn十进制px=long(px)endl; cout*px=*pxn十进制&px=long(&px)endl; cout*px=*pxn十六进制&px=&pxendl;运行结果显示直接输出地址值时是十六进制,若要以十进制显示需做强制类型转换为长整型。【例11.3】编写判断除数为0的整数除法程序#includ

10、evoid fun(int i,int j) if(j)cout商为:i/jendl; else cout除数为0,不能求商!n;void main( ) int x,y; for(int i=0;i3;i+) coutxy; fun(x,y); 请仔细阅读本程序,并与课本上的程序比较。请仔细阅读本程序,并与课本上的程序比较。2.2.使用成员函数使用成员函数put( )put( )输出一个字符输出一个字符putput函数函数原型为:函数函数原型为:ostream &put(char c);ostream &put(char c);使用使用putput函数向屏幕输出字符的格式为:函数向屏幕输出字

11、符的格式为:cout.put(cout.put(字符字符) )【例11.4】用成员函数put( )输出一个字符的例子#includevoid main( ) coutBEIJINGn; cout.put(B).put(E).put(I).put(J).put(I).put(N).put(G).put(n); char c1=65,c2=66,c3=67; cout.put(c1).put(c2).put(c3).put(n); 请仔细阅读本程序,注意函数请仔细阅读本程序,注意函数put()的值是的值是ostream类对象的引用,连续输出时连续加类对象的引用,连续输出时连续加.put()3.3.

12、使用成员函数使用成员函数write( )write( )输出一个字符串输出一个字符串writewrite函数函数原型为:函数函数原型为:ostream &write(const char *str,int n);ostream &write(const char *str,int n);使用使用writewrite函数向屏幕输出字符的格式为:函数向屏幕输出字符的格式为:cout.write(cout.write(字符指针字符指针, ,字符个数字符个数) )【例11.5】用成员函数write( )输出一个字符串的例子#include#includevoid print(char*s)cout.w

13、rite(s,strlen(s).put(n);cout.write(s,6)n;void main( ) char*str=我爱北京天安门!; cout字符串为:str是右移位运算符的重载,格式为:n输入流源头输入流目的地n需从键盘接收数据时,键盘就是输入流源头,输入流目的地应是变量名,头文件iostream.h中定义有istream类的全局对象cin就代表键盘。n提取符依次从输入源中提取一个数据项,连续提取时,数据项之间用空格、制表符、换行等空白符分隔。n如对语句cinxyz;n可键入:18 19 201.1.使用预定义的提取符使用预定义的提取符标准设备(键盘)输入是最不安全的,注意以下几

14、点,可以避免错误: cin为缓冲流。键盘输入的数据保存在缓冲区中,当要提取时,是从缓冲区中拿。如果一次输入过多,会留在那儿慢慢用,如果输入错了,必须在回车之前修改,如果回车键按下就无法挽回了。只有把输入缓冲区中的数据取完后,才要求输入新的数据。不可能用刷新来清除缓冲区,所以不能输错,也不能多输! 输入的数据类型必须与要提取的数据类型一致,否则出错,出错只是在流的状态字state(枚举类型io_state)中对应位置位(置1),程序继续。所以要提高健壮性,就必须在编程中加入对状态字state的判断。 空格和回车都可以作为数据之间的分格符,所以多个数据可以在一行输入,也可以分行输入。但如果是字符型

15、和字符串,则空格(ASCII码为32)无法用cin输入,字符串中也不能有空格。回车符也无法读入。【例11.6】提取符用法示例#includevoid main( ) int x,y; coutxy; cout(x,y)n;2.2.使用成员函数使用成员函数get( )get( )输入一个字符串输入一个字符串getget函数函数原型有多个,其中比较简单的函数函数原型有多个,其中比较简单的2 2个是:个是:char get( );char get( );、istream &get(char c);istream &get(char c);前者提取的字符作为函数值,后者提取的字符放在参数前者提取的字符

16、作为函数值,后者提取的字符放在参数c c使用使用getget函数从键盘提取字符的格式分别为:函数从键盘提取字符的格式分别为:cin.get( )cin.get( )、cin.get(cin.get(字符变量字符变量) )【例11.7】用成员函数get( )从键盘提取字符的例子#includevoid main( ) char ch; cout输入字符串:; while(ch=cin.get( )!=EOF)cout.put(ch); /EOF为文件结束标志,实际是ASCII码26,即请仔细阅读本程序,注意函数请仔细阅读本程序,注意函数cin.get( )的值是字符的值是字符#includevo

17、id main( ) char ch1,ch2; cout输入字符串:; while(cin.get(ch1).get(ch2) cout.put(ch2).put(ch1); 请仔细阅读本程序,注意这种格式的函数请仔细阅读本程序,注意这种格式的函数get( )的值是的值是istream类对象的引用,连续输入时连续加类对象的引用,连续输入时连续加.get( )【例11.8】使用成员函数get带参数的形式输入一个字符#includeconst int N=40;void main( ) char s1N,s2N; couts1;/输入时遇空格、制表符、回车等结束,但这些结束符留在缓冲区中 cou

18、ts1=s1endl; cin.get(s2,N);/从缓冲区中最多接收N-1个字符,放数组s2中,界定符为隐含换行符 couts2=s2endl; 请仔细阅读本程序,请仔细阅读本程序,注意注意get函数的第三种原型:函数的第三种原型:istream &get(char *c,int n,char ch=n);istream &get(char *c,int n,char ch=n); 这种格式的函数这种格式的函数get( )的值是的值是istream类对象的引用,使用格式为:类对象的引用,使用格式为:cin.get(字符指针字符指针,整数整数n,界定符界定符)该函数直接从缓冲区中最多读取n-

19、1个字符数据,若前面遗留有换行,则结束。【例11.9】混合使用成员函数get、提取符输入字符,比较区别3.3.使用成员函数使用成员函数getline( )getline( )输入一行字符输入一行字符getlinegetline函数原型是:函数原型是:istream &getline(char *buf,int n,char ch=n);istream &getline(char *buf,int n,char ch=n);功能是最多提取功能是最多提取n-1n-1个字符放在个字符放在bufbuf为首地址的缓冲区为首地址的缓冲区中,参数中,参数chch为终止符,隐含的终止符为换行符。为终止符,隐含

20、的终止符为换行符。使用使用getlinegetline函数从键盘提取字符串的格式为:函数从键盘提取字符串的格式为:cin.getline(cin.getline(字符指针字符指针,整数整数n,终止界定符终止界定符) )输入字符少于输入字符少于n-1n-1时,接收实际输入字符数,并将缓冲时,接收实际输入字符数,并将缓冲区的回车符清除,若输入字符数不少于区的回车符清除,若输入字符数不少于n-1n-1时,多余的时,多余的字符及回车符留在缓冲区。该函数不能接受换行字符字符及回车符留在缓冲区。该函数不能接受换行字符(n)(n)。该函数终止读取字符的条件为:。该函数终止读取字符的条件为:读取读取n-1n-

21、1个字符个字符遇到参数指定的终止符遇到参数指定的终止符遇到文件结束符遇到文件结束符(Ctrl+Z)(Ctrl+Z)或回车符。或回车符。【例11.10】输入若干行字符,求出最长行的字符个数及输入行数。使用成员函数getline( )#includeconst int SIZE=80;void main( ) char bufSIZE; int lcnt=0,lmax=-1; coutlmax)lmax=count; coutline#lcnt:countendl; cout.write(buf,count).put(n).put(n); coutendl; cout最长行字符数:lmaxendl

22、; cout总行数:lcntendl; 4.使用成员函数使用成员函数read( )输入一行字符输入一行字符read函数原型是:函数原型是:istream &read(char *buf,int n);功能是最多提取功能是最多提取n-1个字符放在个字符放在buf为首地址的缓为首地址的缓冲区中冲区中使用使用read函数从键盘提取字符串的格式为:函数从键盘提取字符串的格式为:cin.getline(字符指针字符指针 ,整数整数n)最多接收最多接收n个字符,接受字符中可以包括换行符个字符,接受字符中可以包括换行符(n)。该函数终止读取字符的条件为:。该函数终止读取字符的条件为:读取读取n个字符个字符遇

23、到文件结束符遇到文件结束符(Ctrl+Z)。【例例11.11】输入若干行字符,并输出。使用成员函输入若干行字符,并输出。使用成员函数数read( )read( )。#includevoid main( ) const int SIZE=80; char bufSIZE=; cout输入若干行字符:n; cin.read(buf,SIZE);cin.read(buf,SIZE); coutendl; coutbuf、readread、getget、getlinegetline四种读取字符方四种读取字符方法的异同法的异同(终止条件、可接受字符的范围、可接受字符的终止条件、可接受字符的范围、可接受字

24、符的多少、使用格式、是否缓冲多少、使用格式、是否缓冲等)。11.311.3 格式化输入输出操格式化输入输出操作作1.1.控制格式的标志位控制格式的标志位定义为公有的无名的枚举类型:定义为公有的无名的枚举类型:enumenum skipws=0x0001, skipws=0x0001, /跳过输入中的空白字符跳过输入中的空白字符 left=0x0002, left=0x0002, /输出左对齐输出左对齐 right=0x0004,right=0x0004, /输出右对齐输出右对齐 internal=0x0008,internal=0x0008, /在输出符号或数字字符后填充在输出符号或数字字符后

25、填充 decdec=0x0010,=0x0010,/在输入输出时将数据按十进制处理在输入输出时将数据按十进制处理 octoct=0x0020,=0x0020,/在输入输出时将数据按八进制处理在输入输出时将数据按八进制处理 hex=0x0040,hex=0x0040,/在输入输出时将数据按十六进制处理在输入输出时将数据按十六进制处理 showbaseshowbase=0x0080,=0x0080,/在输出时带有表示数制基的字符在输出时带有表示数制基的字符 C+在类在类ios中提供格式化输入输出,有两种方法中提供格式化输入输出,有两种方法控制输入输出格式:一是使用标志位和成员函数,控制输入输出格式

26、:一是使用标志位和成员函数,二是使用控制符。二是使用控制符。11.3.1 使用成员函数进行格式输出使用成员函数进行格式输出11.3 11.3 格式化输入输出格式化输入输出操作操作showpointshowpoint=0x0100, =0x0100, /输出浮点数时输出浮点数时, ,必定带小数点必定带小数点 uppercase=0x0200,uppercase=0x0200,/输出十六进制输出十六进制, ,用大写字母用大写字母 showposshowpos=0x0400,=0x0400,/输出正数时输出正数时, ,加加”+”+”号号 scientific=0x0800,scientific=0x

27、0800,/科学计数方式输出浮点数科学计数方式输出浮点数 fixed=0x1000,fixed=0x1000,/定点数方式输出实数定点数方式输出实数 unitbufunitbuf=0x2000,=0x2000,/插插入入后后, ,立立即即刷刷新新流流的的缓缓冲冲区区 stdiostdio=0x4000=0x4000/插入后插入后, ,立即刷新立即刷新stdoutstdout和和stderrstderr该枚举量说明中该枚举量说明中每一个枚举量实际对应两字节数据(每一个枚举量实际对应两字节数据(16位)中位)中的一个位的一个位,所以可以同时采用几个格式控制,只要把,所以可以同时采用几个格式控制,只

28、要把对应位置对应位置1即可,这样既方便又节约内存。取多种控制时,用或即可,这样既方便又节约内存。取多种控制时,用或“|”运运算符来合成,合成为一个长整型数,在算符来合成,合成为一个长整型数,在ios中为:中为:protected:long x_flags;这个长整型数据成员被称为这个长整型数据成员被称为标志字。标志字。11.3 输入输出的格式控制输入输出的格式控制类类iosios中还设置了三个中还设置了三个输入输出流格式控制标志输入输出流格式控制标志:protected:protected: intint x_precisionx_precision; ; /标志浮点数精度标志浮点数精度, ,

29、缺省为缺省为6 6位位 intint x_widthx_width; ; /输出域宽输出域宽, ,缺省域宽为缺省域宽为0 0, /重设域宽只对其后第一输出项有效重设域宽只对其后第一输出项有效, ,如域宽不足如域宽不足, ,则不受限则不受限制制 char char x_fillx_fill; ; /标志域宽有富余时填入的字符标志域宽有富余时填入的字符2. 设置标志字的成员函数设置标志字的成员函数long flags( ) 返回标志字函数。返回标志字函数。long flags(long) 函数值为更新前的标志字,参数作更新后的标志字函数值为更新前的标志字,参数作更新后的标志字long setf(l

30、ong setbits,long field)该函数先将第二个参数(转换为二进制)中为1的标志位置0,再将第一个参数(转换为二进制)中为1的标志位置1 。函数值为设置前标志字。long setf(long)设置参数(转换为二进制)中为1的标志位置1,其余标志位不变。函数值未设置前的标志字。long unsetf(long)设置参数(转换为二进制)中为 1的标志位置0,其余标志位不变。函数值未设置前的标志字。在ios中定义有如下静态整型常量:static const long adjustfield;其值其值=left|right|internal=0x2|0x4|0x8=0xestatic c

31、onst long basefield;其值其值=dec|oct|hex=0x10|0x20|0x40=0x70static const long floatfield;其值其值=scientific|fixed=0x800|0x1000=0x1800实际上,上述3个组合设置是有矛盾的,如中又要左对齐,又要右对齐是不可能的,自己可以编程测试实际结果,上述组合常用于清除标志位。例如,若需清除数制标志后,再设置十六进制标志,可调用成员函数:cout.setf(ios:hex,ios:basefield)3. 3. 控制输出格式的成员函数控制输出格式的成员函数IOS类中有如下控制输出格式的成员函数:

32、int width( ); int width(int); 前者函数值为当前输出的数据宽度;后者参数为设置的数据输出宽度,函数值为设置前的数据输出宽度值;默认为实际需要的最少字符数,设置宽度小于默认值时,设置无效。char fill( ); char fill(char); 前者函数值为当前使用的填充字符;后者参数为设置的填充字符,函数值为设置前使用的填充字符;默认填充字符为空格。int precision( ); int precision(int); 前者函数值为当前使用的浮点数有效数字个数;后者参数为设置的浮点数有效数字个数,函数值为设置前使用的浮点数有效数字个数;单精度最多7位(默认6

33、位)有效数字,双精度最多15位(默认6位)有效数字,长双精度最多19位(默认6位) 有效数字。【例11.12】设置清除标志位的例子#includevoid main( ) int a=1234;double b=12.345678; coutcout.flags( )endl; cout.setf(ios:hex,ios:basefield); coutcout.flags( )endl; coutaendl; cout.setf(ios:showbase);coutaendl; cout.setf(ios:uppercase);coutaendl; cout.setf(ios:oct,ios

34、:basefield);coutaendl; long oldflag=cout.setf(ios:dec,ios:basefield); coutaendl; cout.setf(ios:showpos); coutaendl; cout.flags(oldflag); coutaendl; coutcout.flags( )endl;coutbendl; cout.setf(ios:scientific,ios:floatfield);coutbendl; coutcout.flags( )endl; /运行程序,观察结果。运行程序,观察结果。【例11.13】设置控制小数位数的例子#inc

35、ludevoid main( ) double d1=12.34567,d2=12.000; coutd1endld2endl; cout.setf(ios:showpoint); coutd1endld2endl;运行程序,观察结果运行程序,观察结果, ,注意:注意:默认的是可以不带小数点及小数部分的默认的是可以不带小数点及小数部分的0 0默认的有效数字是默认的有效数字是6 6位。位。【例11.14】设置输出对齐格式的例子#includevoid main( ) cout12345678901234567890n; int i=12345; coutiendl; cout.width(10)

36、; cout.fill(#); cout.setf(ios:left,ios:sdjustfield ); coutiendl; cout.setf(ios:right,ios:sdjustfield ); coutiendl; cout.precision(6); double d=123.456789; coutdendl; cout.setf(ios:scientific,ios:floatfield);coutdendl; cout宽度:cout.width( );运行程序,观察结果,注意运行程序,观察结果,注意宽度设置一次有效,再次使用宽度设置一次有效,再次使用需重新设置,需重新设置

37、,设置有冲突时会怎模样?怎样研究这个问设置有冲突时会怎模样?怎样研究这个问题?题?11.3.2 使用控制符进行格式输出n控制符又称操作子,是定义在头文件iomanip.h中的对象,可以直接插入到数据流中,被操作。n下表列出了VC+支持的操作子:操作符操作符含含义 输入入/输出出 dec以十以十进制制显示示(默默认设置置) I/Ohex以十六以十六进制制显示示 I/Ooct以八以八进制制显示示 I/OSetbase(int n)设置数制基数为设置数制基数为n(=0,8,10,16),0表示默认表示默认(十进制十进制) I/Ows提取空白字符提取空白字符 I ends插入空字符插入空字符 Oend

38、l 插入插入换行符,然后刷新行符,然后刷新ostream缓冲区冲区 Oflush 刷新刷新ostream缓冲区冲区 O resetiosflags(long)清除参数所指定的标志位清除参数所指定的标志位 I/Osetiosflags(long)设置参数所指定的标志位设置参数所指定的标志位 I/Osetfill(char)设置填充字符置填充字符 Osetprecision(int)设置浮点数输出的有效数字位数设置浮点数输出的有效数字位数 Osetw(int)设置置输出数据出数据项的域的域宽 O【例11.15】按整数的不同基数设置输出格式的例子#include#includevoid main(

39、) int n; coutn; coutn的十六进制形式为:hexnendl; coutdecn的八进制形式为:octnendl; coutdecn的十进制形式为:nendl;运行程序,观察结果,注意进位制基数设置后运行程序,观察结果,注意进位制基数设置后永久有永久有效,要改变必须重新设置效,要改变必须重新设置。【例11.16】设置浮点数精度和填充符的例子#include#include#includevoid main( ) double n=sqrt(3); for(int i=0;i10;i+) coutsetprecision(i)setw(12)setfill(*); coutnen

40、dl; 运行程序,观察结果,注意输出宽度、输出精度运行程序,观察结果,注意输出宽度、输出精度( (有有效数字位数效数字位数) )、填充字符等设置方法。、填充字符等设置方法。【例11.17】利用设置填充符、宽度的方法输出菱形#include#includevoid main( ) for(int i=7;i1;i-)coutsetfill( )setw(i) setfill(*);coutsetw(15-2*i)*endl; for(i=1;i8;i+) coutsetfill( )setw(i) setfill(*); coutsetw(15-2*i)*endl; 运行程序运行程序,观察结果观

41、察结果,注意打印图形的算法研究注意打印图形的算法研究,找各找各行字符个数的规律行字符个数的规律,注意与注意与【例例4.16】比较。比较。11.4 插入符()的重载为了对类的对象进行插入及提取操作,可以编写重载函数实现插入符、提取符的重载。【例11.18】重载提取符和插入符,实现中国日期格式的输入输出。(类定义、重载运算符的友元函数定义)#includeclass Date public:Date(int y,int m,int d)Year=y;Month=m;Day=d; friend ostream&operator(istream&stream,Date&date); private:i

42、nt Year,Month,Day; ;ostream&operator(ostream&stream,Date&date) streamdate.Year年年date.Month 月月date.Day(istream&stream,Date&date) streamdate.Yeardate.Monthdate.Day; return stream; 【例11.18】重载提取符和插入符,实现中国日期格式的输入输出。(主函数定义)void main( ) Date d(2003,3,18); cout当前日期是:dd; cout新日期:d;上述主程序中,有5个插入符(),这些符号中哪些使用了友

43、元函数定义的运算符重载,如何区别是否重载?11.511.5 磁盘文件的输入和输出操作磁盘文件的输入和输出操作 本本节节中中文文件件指指的的是是磁磁盘盘文文件件。C+根根据据文文件件(file)内内容容的的数数据据格格式式,可可分分为为两两类类:二二进进制制文文件件和和文文本本文文件件。文文本本文文件件由由字字符符序序列列组组成成,也也称称ASCII码码文文件件,在在文文本本文文件件中中存存取取的的最最小小信信息息单单位位为为字字符符(character),而而二进制文件二进制文件中存取的最小信息单位为字节(中存取的最小信息单位为字节(Byte)。)。11.5.111.5.1 文件的打开与关闭文

44、件的打开与关闭 11.5.211.5.2 文本文件的读写文本文件的读写11.5.311.5.3 二进制文件的读写二进制文件的读写 11.5.4 11.5.4 随机随机文件的读写文件的读写 11.5.511.5.5 文件操作的文件操作的其它函数其它函数 11.5 磁盘文件的输入与输出操作磁盘文件的输入与输出操作11.5.1 文件的打开和关闭操作文件的打开和关闭操作1.打开文件打开文件说明一个文件流对象,这又被称为说明一个文件流对象,这又被称为内部文件内部文件:ifstream 输入文件流对象名输入文件流对象名;/只可用于输入只可用于输入ofstream 输出文件流对象名输出文件流对象名;/只可用

45、于输出只可用于输出fstream 输入输出文件流对象名输入输出文件流对象名; /既可用于输入又可用于输出既可用于输入又可用于输出 使用对象的成员函数使用对象的成员函数open打开文件:打开文件:文件流对象名文件流对象名.open(文件名文件名,打开方式,打开方式);此此处处的的文文件件名名必必须须是是外外存存上上的的文文件件名名(外外部部文文件件),必必要要时时应应指指明明路路径径,open函函数数的的作作用用是是在在内内部部文文件件与与外外部部文文件件之之间间建建立立联联系。系。、两两步步可可以以和和二二而而一一,即即用用对对象象初初始始化化时时的的构构造造函函数数代代替替open函数,如函

46、数,如:ifstream 输入文件流对象名输入文件流对象名(文件名文件名,打开方式打开方式)文件访问方式常量表文件访问方式常量表(ios中定义的公有枚举常量中定义的公有枚举常量)方式名称(16进制值)含义(用途)in=0x001 以输入方式打开文件(读文件)out=0x002 以输出方式打开文件(写文件)app=0x008以输出追加方式打开(在文件末尾追加)ate=0x004打开文件时,文件置文件尾trunc=0x010清除文件内容或创建新文件binary0x080以二进制方式打开文件,缺省时为文本nocreate=0x020打开已有文件,不创建新文件noreplace=0x040不替换文件内

47、容,若文件存在且未设app和ate,则打开失败ios:in|ios:out以可读可写方式打开文件ios:out|ios:binary以写二进制文件方式打开(向文件输出)ios:in|ios:binary以读二进制文件方式打开(从文件输入)11.5.1 11.5.1 文件的打开和关闭操作文件的打开和关闭操作文件流中三个打开文件的成员函数文件流中三个打开文件的成员函数(open)的原型为:的原型为:void ifstream:open(const char*,int=ios:in, int=filebuf:openprot);void ofstream:open(const char*,int=i

48、os:out, int=filebuf:opernprot);void fstream:open(const char*,int, int=filebuf:openprot); 第一个参数为要打开的磁盘文件名。第二个参数为打开方式,第一个参数为要打开的磁盘文件名。第二个参数为打开方式,有输入(有输入(in)、输出()、输出(out)等。第三个参数为指定打开文件的)等。第三个参数为指定打开文件的保护方式,一般取缺省。保护方式,一般取缺省。例如:要新建磁盘文本文件例如:要新建磁盘文本文件file.txt,并置写状态并置写状态,可如下进行可如下进行: ofstream outfile; outfil

49、e.open(file.txt,ios:out);或者:或者:ofstream outfile(file.txt,ios:out);或者:或者:ofstream outfile; outfile.open(file.txt);或者:或者:ofstream outfile(file.txt);11.5.1 11.5.1 文件的打开和关闭操作文件的打开和关闭操作打打开开文文件件也也应应该该判判断断是是否否成成功功,若若成成功功,文文件件流流对对象象值值为为非非零零值值,不不成成功功为为0(NULL),文文件件流流对对象象值值物理上就是指它的地址物理上就是指它的地址。下面是打开一个文件的完整程序段:

50、下面是打开一个文件的完整程序段:fstream iofile(myfile.txt,ios:in|ios:out);if(!iofile)cout不能打开文件不能打开文件:myfile.txtendl; exit(1); /失败退回操作系统失败退回操作系统2. 关闭文件操作关闭文件操作关关闭闭文文件件将将清清理理与与打打开开的的文文件件有有关关的的内内存存与与外外存存,这这样样即即可可减减少少内内存存负负担担又又可可保保证证文文件件信信息息安安全全。关关闭闭文文件使用成员函数件使用成员函数close进行:进行:文文件件流流对对象象名名.close( );/文文件件流流对对象象名名就就是是内内部

51、部文文件件名名。11.5.2 文本文件的读写操作文本文件的读写操作【例11.19】使用插入符向文本文件中写信息#include/定义标准输出流对象定义标准输出流对象cout#include/定义文件流类定义文件流类fstream#include/定义定义abort函数函数void main( )fstream outfile; outfile.open(file1.dat,ios:out); if(!outfile)coutfile1.dat打不开!打不开!n;abort(); outfile这是一个程序。这是一个程序。n这是一个字符串。这是一个字符串。nok; outfile.close(

52、); 注意分析程序中的注意分析程序中的3个插入符个插入符()的作用的作用注意注意3个包含文件的作用个包含文件的作用注意该程序的运行结果如何检验注意该程序的运行结果如何检验函数函数abort( )的作用。的作用。【例11.20】使用成员函数getline将文本文件file1.dat中的信息读出并显示在屏幕上。#include/定义标准输出流对象定义标准输出流对象cout#include/定义文件流类定义文件流类ifstream#include/定义定义abort函数函数void main( )ifstream infile(file1.dat); if(!infile)coutfile1.dat

53、打不开!打不开!n;abort(); char s80; while(!infile.eof( ) infile.getline(s,sizeof(s);coutsendl; infile.close( );注意,定义内部文件与打开文件的格式与例19的区别 循环条件的含义 读取文件信息是否可用提取符?【例11.21】使用成员函数get、put读写文本文件。#include/定义标准输出流对象定义标准输出流对象cout#include/定义文件流类定义文件流类fstream#include/定义定义abort函数函数#include/定义定义strlen函数函数void main( )fstre

54、am infile,outfile(file2.dat,ios:out); if(!outfile)coutfile2.dat打不开!打不开!n;abort( ); char s= 我喜欢我喜欢C程序设计。程序设计。; for(int i=0;i=(int)strlen(s);i+)outfile.put(si); outfile.close( ); infile.open(file2.dat,ios:in); if(!infile)coutfile2.dat打不开!打不开!n;abort( ); char ch;while(infile.get(ch)cout.put(ch); couten

55、dl;infile.close( );注意,该程序中共有几个内部文件?有几个外部文件?内外如何对应?用操作系统的办法如何显示本程序产生的外部文件?【例11.22】编程拷贝文本文件,使用成员函数get、put读写。#include/定义标准输出流对象定义标准输出流对象cout#include/定义文件流类定义文件流类fstream#include/定义定义abort函数函数void main( )fstream infile(file2.dat,ios:in),outfile(file3.dat,ios:out); if(!infile)coutfile2.dat打不开!打不开!n;abort(

56、 ); if(!outfile)coutfile3.dat打不开!打不开!n;abort( ); char ch; while(infile.get(ch) outfile.put(ch); infile.close( );outfile.close( ); 注意,该程序中共有几个内部文件?几个外部文件?内外如何对应?该程序运行前必须有哪些先决条件?该程序运行后会产生什么结果?能否用操作系统的办法检验本程序的成果?11.5.3 二进制文件的读写操作二进制文件的读写操作n二进制文件打开方式中应指定:ios:binaryn写二进制文件使用成员函数:write( )n读二进制文件使用成员函数:rea

57、d( )n这两个函数定义在fstream.h中原型分别为:ostream& write( const char* pch, int n );istream& read( char* pch, int n );n第第1个参数要读写的字符指针,即字符串,向文件中写时,个参数要读写的字符指针,即字符串,向文件中写时,字符串不能被改变;字符串不能被改变;n第第2个参数为要读写字符的个数。个参数为要读写字符的个数。n函数的使用格式为:二进制内部文件名二进制内部文件名.write(待写入的字符串地址待写入的字符串地址,字符串长度字符串长度)二进制内部文件名二进制内部文件名.read(字符串读入地址字符串读

58、入地址,字符串长度字符串长度) 【例11.23】使用成员函数read、write读写二进制文件#include/定义标准输出流对象定义标准输出流对象cout#include/定义文件流类定义文件流类fstream#include/定义定义abort函数函数struct personchar name80;double height;unsigned short age;person people5=马马,1.78,35,张张,1.68,24,胡胡,1.90,40,鲁鲁,1.89,50,郎郎,2,18;void main( ) fstream file(file4.dat,ios:in|ios:

59、out|ios:binary); if(!file)coutfile4.dat打不开!打不开!n;abort( ); for(int i=0;i5;i+) file.write(char*)&peoplei,sizeof(peoplei); file.seekp(0,ios:beg);/文件写指针定位函数,本句定位开头文件写指针定位函数,本句定位开头 for(i=0;i5;i+)file.read(char*)&peoplei,sizeof(peoplei); coutpeoplei.nametpeoplei.heightt; coutpeoplei.ageendl; file.close(

60、); 【例11.24】存储本科生、硕士生信息文件(定义本科生)#include/定义标准输出流对象定义标准输出流对象cout#include/定义文件流类定义文件流类fstream#include/定义字符串处理函数定义字符串处理函数#include/定义输入输出控制符(控制子)定义输入输出控制符(控制子)class Studentpublic:Student(char*pN,unsigned num,double g) strcpy(Name,pN);uID=num;grade=g; virtual void Print(ostream &out); friend ostream&opera

61、tor(ostream&out,Student&st); private:char Name80;unsigned uID;double grade; ;void Student:Print(ostream&out) out.setf(ios:left,ios:adjustfield); out.width(15);outNameuID; out.setf(ios:right,ios:adjustfield); out.width(8);outgrade; ostream&operator(ostream&out,Student&st) st.Print(out); outendl; retu

62、rn out; 【例11.24】存储本科生、硕士生信息文件(定义研究生)class Master:public Studentpublic:Master(char*pN,unsigned num,double g,char*pdN): Student(pN,num,g) strcpy(dName,pdN); void Print(ostream&out); private:char dName80; ;void Master:Print(ostream&out) Student:Print(out); out dName; void main( ) ofstream out(abc.txt);

63、 / if(!out)coutabc.txt打不开!打不开!n;abort( ); Student s1(王萍王萍,99001,96.5); Master s2(马光马光,99056,84.8,胡胡), s3(江芳江芳,99078,90,黄黄); outs1s2s3; out.close( ); 注意注意,插入符是重载的插入符是重载的,插入符的重载定义中插入符的重载定义中,Print动态联编。动态联编。11.5.4 随机文件的读写操作 从文件头开始读或从文件尾开始写,称为顺序读写 在文件的任意位置进行读写操作,称为随机读写操作,可随机读写的文件称为随机文件。 随机读写文件需要:按读写方式打开文

64、件使用定位函数将读写指针定位到所需位置,读写指针只有一个,但是有读、写两组函数对它进行操作使用读写函数对文件进行读写读指针定位的成员函数为:seekg( ) 其原型为 istream& seekg( 位置位置 ); istream& seekg( 偏移量偏移量 ,参照位置参照位置);其中其中位置位置和和偏移量偏移量为长整数为长整数,参照位置为下列3个之一:ios:beg(值为0)、ios:cur(值为1)、ios:end(值为2)分别表示文件开头、当前位置、文件结尾 写指针定位的成员函数为:seekp( )其原型为 ostream& seekp( 位置位置 ); ostream& seekp(

65、 偏移量偏移量 ,参照位置参照位置);其中其中位置位置和和偏移量偏移量为长整数为长整数,参照位置为下列3个之一:ios:beg(值为0)、ios:cur(值为1)、ios:end(值为2)分别表示文件开头、当前位置、文件结尾取当前读指针位置的成员函数原型为:long teelg( )取当前写指针位置的成员函数原型为:long teelp( )这两个取指针位置函数返回的长整数表示读写的当前位置距离文件开头的字节数。一般指针定位、取指针位置的函数的使用格式为:内部文件名.seekp(偏移量,参照位置)内部文件名.seekg(偏移量,参照位置)内部文件名. tellg( )、内部文件名. tellp

66、( ) 文件读写结束应注意使用close函数关闭文件【例11.25】存储整数的二进制文件#include#include#includevoid main( ) fstream file(file5.dat,ios:in|ios:out|ios:binary); if(!file)coutfile5.dat打不开!打不开!n;abort( ); for(int i=1;i=20;i+)file.write(char*)&i,4); long pos=file.tellp( );cout当前字节数当前字节数:posendl; for(i=21;i=50;i+) file.write(char*)

67、&i,4); file.seekp(pos);file.read(char*)&i,4); cout存储的数据是存储的数据是:iendl; file.seekg(0,ios:beg);for(i=51;i=100;i+)file.write(char*)&i,4); file.seekg(pos);file.read(char*)&i,4);/此时指针指向哪个整数?此时指针指向哪个整数? cout存储的数据是存储的数据是:iendl; file.seekp(112,ios:cur);file.read(char*)&i,4); cout存储的数据是存储的数据是:iendl; /此时的此时的i是

68、第几个整数?是第几个整数? cout当前字节数当前字节数:file.tellp( )endl; file.close( ); 注意注意,文件中文件中读读写数字的方法写数字的方法,读写指针定位的方法读写指针定位的方法。【例11.26】存储对象数组的二进制文件#include#include#includevoid main( ) struct student char name50;long number;double totalscord;stu5= 马马,202001,85.5,李李,202023,85.9,郭郭,202045,91.2,胡胡,202067,93.1,严严,202076,78

69、.5; int len=sizeof(student); student s1;fstream file1(file6.dat,ios:out|ios:in|ios:binary); if(!file1)coutfile6.dat打不开!打不开!n;abort( ); for(int i=0;i5;i+)file.write(char*)&stui,len); file1.seekg(len*4);file1.read(char*)&s1,len); couts1.namets1.numberts1.totalscordendl; file1.seekg(len*1);file1.read(c

70、har*)&s1,len); couts1.namets1.numberts1.totalscordendl; file1.close( ); 注意注意,文件中文件中读读写写对象对象的方法的方法,读写指针定位的方法读写指针定位的方法。11.5.5 文件操作的其它函数1.跳过输入流中指定数量的字符的成员函数原型为:istream &ignore(int=1,int=EOF);使用格式为使用格式为:内部文件名内部文件名.ignore(跳过字符数跳过字符数,终止符终止符)功能是:功能是:从输入流的当前位置跳过指定个数字符,或遇到终止从输入流的当前位置跳过指定个数字符,或遇到终止符为止,终止符仍留在输

71、入流中。隐含终止符为符为止,终止符仍留在输入流中。隐含终止符为Ctrl+Z【例例11.27】正确输入一个整数的程序正确输入一个整数的程序#includevoid main( )int a;couta; while(!cin)cin.clear( );cin.ignore(80,n); couta; cout输入的整数是输入的整数是:aendl; 函数函数clear清除错误输入设置的状态字,使输入流恢复正常清除错误输入设置的状态字,使输入流恢复正常函数函数ignore则跳过一行错误的输入。则跳过一行错误的输入。 2.2.退回一个字符到输入流中的函数退回一个字符到输入流中的函数原型为:istrea

72、m &putback(char);使用格式为使用格式为:内部文件名内部文件名.putback(先前输入的字符先前输入的字符)功能是:将指定字符退回输入流中功能是:将指定字符退回输入流中【例例11.28】将输入的字符串中的数字字符串输出在屏幕上将输入的字符串中的数字字符串输出在屏幕上#include#includeint getnum(char*s) int flag=0;char ch; while(cin.get(ch)&!isdigit(ch);/连续跳过非数字字符连续跳过非数字字符 if(!cin) return 0;/遇输入流结束符遇输入流结束符(Ctrl+Z)返回返回0 do*s+=

73、ch;while(cin.get(ch)&isdigit(ch);/连续读入数字连续读入数字 *s=0;flag=1;if(cin)cin.putback(ch);return flag; void main( )char buf80; cout输入字符串:输入字符串:; while(getnum(buf) cout数字字符串为:数字字符串为:bufendl; coutbufch; /从字符串流对象从字符串流对象(串串)读入一个字符读入一个字符 coutchendl; /输出输出T【例例11.29】使用使用字符串流输出字符串流输出,注意程序中的注意程序中的cout、out1的区别的区别#inc

74、lude#includevoid main( ) char buf80;ostrstream out1(buf,sizeof(buf);int m=25; for(int i=0;i6;i+)out1m=(m+=10); out10; coutbuf:bufendl;double d=123.45678; out1.setf(ios:fixed|ios:showpoint); out1.seekp(0);out1d的值是的值是:d0; coutbufendl;char *pstr=out1.str( ); coutpstrendl; 【例例11.30】使用使用字符串流输入字符串流输入,注意注意

75、比较比较下述下述ss与与cin#include#includevoid main( ) int a,a1;double b,b1;char c80,c180; char buf=1234 2.79n串串; istrstream ss(buf); ssabc; couta+b,cendl; couta1b1c1; couta1+b1,c1endl;【例例11.31】带带字符串流长度的输入字符串流长度的输入,比较比较s1与与s2的区别的区别#include#includevoid main( ) char buf=12345yu; int i,j; istrstream s1(buf);/长度有长

76、度有8位位 istrstream s2(buf,2);/长度只有长度只有2位位 /串流中不自动存放串结束符串流中不自动存放串结束符(0) s1i; s2j; couti,j,i+jendl;11.7 流错误处理流类库中提供错误检测和处理机制。11.7.1 错误状态字和状态函数ios类中定义有记录错误的状态字和检测、设置、清除状态字的成员函数。ios的状态字常量有: goodbit=0x00 表示无错状态 eofbit=0x01 表示读写指针到达文件尾 failbit=0x02 表示读写失败 badbit=0x04 表示试图非法操作 hardbit=0x08 表示出现致命错误 11.7.1 错误

77、状态字和状态函数ios中的状态函数有: int rdstate( ) 返回当前错误状态字 int eof( ) 提取操作到达流尾则返回非0,否则返回0 int fail( ) failbit位设置,返回非0,否则返回0 int bad( ) badbit位设置,返回非0,否则返回0 int good( ) 状态字为goodbit,返回非0,否则返回0 void clear(状态字=ios:goodbit) 使用新状态字设置错误状态位(隐含设置无错,即清除错误状态字),但不能清除hardbit位【例例11.32】测试流对象测试流对象cin错误的状态的程序错误的状态的程序#includevoid

78、main( ) int a;couta;/正常输入后的状态字正常输入后的状态字 coutcin.rdstate( ):cin.rdstate( )ncin.eof( ):cin.eof( ); coutncin.bad( ):cin.bad( )ncin.fail( ):cin.fail( ); coutncin.good( ):cin.good( )a; /错误输入后的状态字错误输入后的状态字 coutncin.rdstate( ):cin.rdstate( )ncin.eof( ):cin.eof( ); coutncin.bad( ):cin.bad( )ncin.fail( ):cin

79、.fail( ); coutncin.good( ):cin.good( )endl; cin.clear( ); coutncin.good( ):cin.good( )endl; cin.clear(ios:failbit);coutcin.good( ):cin.good( )endl;小结与作业小结与作业C中所有的输入与输出均用流来表示输入与输出应注意流出的发源地与流向目的地所有对于流的操作均由流对象来实现屏幕作为输出设备是流向的目的地,用coutcout表示表示键盘作为输入设备是流的发源地,用cincin表示表示插入符是从流对象中获取,保存在内存中文件分内部文件、外部文件,分文本文件、二进制文件,分顺序读写文件、随机读写文件内部文件就是流对象,由内部文件就是流对象,由C+C+处理处理外部文件由操作系统处理,保存在外存中作业:作业题作业:作业题11全做全做

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 高等教育 > 研究生课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号