第九章C的输入和输出.ppt

上传人:本田雅阁 文档编号:3441188 上传时间:2019-08-26 格式:PPT 页数:45 大小:342.54KB
返回 下载 相关 举报
第九章C的输入和输出.ppt_第1页
第1页 / 共45页
第九章C的输入和输出.ppt_第2页
第2页 / 共45页
第九章C的输入和输出.ppt_第3页
第3页 / 共45页
第九章C的输入和输出.ppt_第4页
第4页 / 共45页
第九章C的输入和输出.ppt_第5页
第5页 / 共45页
点击查看更多>>
资源描述

《第九章C的输入和输出.ppt》由会员分享,可在线阅读,更多相关《第九章C的输入和输出.ppt(45页珍藏版)》请在三一文库上搜索。

1、1,第9章 C+的输入和输出,本章主要内容 9.1 C+为何建立自己的输入输出系统 9.2 C+的流库及其基本结构 9.3 预定义类型的输入输出 9.4 用户自定义类型的输入输出 9.5 文件的输入输出 本章重点 预定义类型、用户自定义类型与文件的输入输出 本章难点 用户自定义类型的输入输出的格式及文件的输入输出 本章所需学时: 4 学时,2,9.1 C+为何建立自己的输入输出系统,数据的输入输出对于程序设计来说是很重要的,但在C和C+中并没有专门的输入输出语句,在C+中的I/O操作而是通过一组标准I/O函数和I/O流来实现的。 C+的标准I/O函数是从C语言继承而来的,同时对C语言的标准I/

2、O函数进行了扩充。C+的I/O流不仅拥有标准I/O函数的功能,而且比标准I/O函数功能更强、更方便、更可靠。 C+的流类比C的输入输出函数具有更大的优越性: 首先它是类型安全的,可以防止用户输出数据与类型不一致的错误。 C+中可以重载运算符“”和“”,使之能识别用户自定义的类型,并且像预定义类型一样有效方便。 C+输入输出的书写形式也很简单、 清晰,这使程序代码具有更好的可读性。,3,9.2 C+的流库及其基本结构,C+的流 输入输出是一种数据传递操作,它可以看作字符序列在主机与外部介质之间的流动。 流是从源(source,或产生者)到矢(sink,或消费者)的数据流的抽象引用。从源输入字符称

3、为提取(extracting);把字符输出到矢称为插入(inserting) 流具有方向性 在C+中包含几个预定义的流:cin、cout、cerr和clog流 对流对象进行抽象就得到了流类,流类形成的层次结构就构成了流类库,即流库,4,流类库 C+流库用继承的方式来建立一个输入输出类库,它具有两个平行的基类:streambuf类和ios类。其他类都是从这两个类直接或间接派生而来的 streambuf类提供物理设备的接口或对缓冲区的低级操作但一般很少直接使用,而是使用由它直接派生而来有以下三类 : filebuf类使用文件来保存缓冲区中的字符序列 strstreambuf类提供了在内存中进行提取

4、和插入操作的缓冲区管理 conbuf类用于输出处理,如控制光标、设置颜色、定义活动窗口、清屏、清一行等功能,5,ios类 ios类与它的派生类为用户使用流类的接口,它们均有一个指向streambuf的指针。ios类使用streambuf及其派生类完成错误格式化输入输出,并支持对streambuf的缓冲区进行输入输出时的格式化或非格式化转化 它直接派生四个类:输入流类istream、输出流类ostream、文件流类fstreambase和字符串流类strstreambase 输入文件流类ifstream同时继承了输入流类和文件流基类(当然对于根基类是间接继承),输出文件流类ofstream同时继

5、承了输出流类和文件流类,输入字符串流类istrstream同时继承了输入流类和字符串流基类,输出字符串流类ostrstream同时继承了输出流类和字符串流基类,输入输出流类iostream同时继承了输入流类和输出流类,输入输出文件流类fstream同时继承了输入输出流类和文件流基类,输入输出字符串流类strstream同时继承了输入输出流类和字符串流基类。,6,C+系统中的I/O类库,其所有类被包含在iostream.h,fstream.h和strstrea.h这三个系统头文件中,各头文件包含的类如下: iostream.h包含有:ios, iostream, istream, ostream

6、, iostream_withassign, istream_withassign, ostream_withassign等。 fstream.h包含有:fstream, ifstream, ofstream和fstreambase,以及iostream.h中的所有类。 strstrea.h包含有:strstream, istrstream, ostrstream和strstreambase,以及iostream.h中的所有类。,7,9.3 预定义类型的输入输出,无格式输入输出 基于C+类库的输入输出流需要使用两个流对象cin和cout,还要用与之相配套的两个输入输出运算符和变量 cout运算

7、符进行重载: cin.operator(变量) cout.operator(变量和常量),8,输出运算符 从运算符角度来看,输出通过输出运算符“”来完成的,输出运算符“”也称插入运算符,它是一个双目运算符,有两个操作数,左操作数为。stream类的一个对象(如cout),右操作数为一个系统预定义类型的常量或变量。 输出运算符“”采用左结合方式工作,并且返回它的左操作数,因此,可以把多个输出组合到一个语句中工作,使用起来很方便。 在使用输出运算符“”进行输出操作时,不同类型的变量也可以组合在一条语句中。,9,输入运算符 从运算符角度来看,输入操作通过输入运算符“”来完成。输入运算符“”也称提取运

8、算符,它也是一个双目运算符,有两个操作数,左面的操作数是istream类的一个对象(cin),右面的操作数是系统预定义的任何数据类型的变量。 在缺省情况下,运算符“”将跳过空白符,然后读入后面的与变量类型相对应的值。 当输入字符串(即类型为Char“的变量)时,运算符“”的作用是跳过空白,读入后面的非空白字符,直到遇到另一个空白字符为止,并在串尾放一个字符“0”。 因此,输入字符串遇到空格时,就当作本数据输入结束。,10,数据输入时,系统除检查是否有空白外,还检查输入数据与变量的匹配情况。 在缺省情况下,运算符“”将跳过空白符,因此,对一组变量输入值时可用空 格或换行将数值之间隔开。 输入输出

9、格式控制 在C+提供了两种进行格式控制的方法: 使用ios类中有关格式控制的成员函数; 操纵符的特殊类型的函数,11,使用ios类中的成员函数进行输入输出格式控制时,由通过对格式状态字、域宽、填充字符以及输出精度的操作完成。输入输出格式是由一个long int 类型的状态自来决定。在 ios类的 public部分定义了一个枚举,它的每个成员分别定义状态标志字的一个位,每一位都称为一个状态标志位。这个枚举定义如下: public: enum skipws= 0x0001, /跳过输入空格 left= 0x0002, /输出左对齐 right= 0x0004, /输出右对齐 internal= 0

10、x0008, /符号和进制指示符后的填补 dec= 0x0010, /十进制转换 oct= 0x0020, /八进制转换 hex= 0x0040, /十六进制转换,12,showbase= 0x0080, /输出时显示进制指示符 showpoint= 0x0100, /显示十进制小数点 uppercase= 0x0200, /大写十六进制输出 showpos= 0x0400, /正整数前显示“+” scientific= 0x0800, /科学计数表示法表示浮点数 fixed= 0x1000, /小数形式标识符点数 unitbuf= 0x2000, /在插入后刷新所有流 stdio= 0x40

11、00 / 刷新 stdout, ;,13,设置状态标志,即是将某一状态标志“1”,可使用setf()函数 其一般格式为: long ios:setf(long flags) 其调用格式为: 流对象.setf(ios:状态标志) 消除状态标志,即是将某一个状态标志“0”,可使用unsetf()函数 其一般格式为: long ios:unsetf(long flags) 其调用格式为: 流对象.unsetf(ios:状态标志) 取状态标志,可使用flags()函数,有两种情况: long ios:flags(long flag) long ios:flags() 前者将状态标志字设置为flag,并

12、返回设置前的状态标志字;但与setf()函数的区别在于:setf()函数是原有的基础上追加设定,而flags()函数是用新设定来覆盖以前的状态标志字。 后者用于返回当前的状态标志字。,14,例9-2来说明几个函数的用法 #include void showflags(long f) long i; for(i=0x8000;i;i=i1) if(i,15,设置域宽,主要是用来控制输出。设置域宽的成员函数有两个: int ios:width(); int ios:width(int w) 前者用来返回当前的域宽值;后者用来设置域宽,并返回原来的域宽。注意,所设置的 域宽仅对下一个流输出操作有效,

13、当一次输出操作完成之后,域宽又恢复为0。 填充字符,填充字符有两个成员函数: int ios:fill(); int ios:fill(char ch) 前者用来返回当前的填充字符,后者用ch重新设置填充字符,并返回设置前的填充字符 设置显示的精度 int ios:precision(int p); 此函数用来重新设置浮点数所需小数的位数,并返回设置前的小数点后的位数 例9-3来说明几个函数的用法,16,#include main() cout“x_width=“cout.width()endl; cout“x_fill=“cout.fill()endl; cout“x_precision=“

14、cout.precision()endl; cout123“ “123.45678“ “234.567endl; cout“-“endl; cout“* x_width=10,x_fill= ,x_precision=4*n“; cout.width(10);cout.precision(4); cout123“ “123.45678“ “234.567endl; cout“x_width=“cout.width()endl; cout“x_fill=“cout.fill()endl; cout“x_precision=“cout.precision()endl; cout“-“endl; c

15、out“* x_width=10,x_fill=,17,cout123“ “123.45678endl; cout.setf(ios:left);cout.width(10); cout123“ “123.45678endl; cout“x_width=“cout.width()endl; cout“x_fill=“cout.fill()endl; cout“x_precision=“cout.precision()endl;return 0;,18,使用预定义的操作符进行I/O格式控制 使用ios类中的成员函数进行I/O格式控制时,每个函数的调用需要写一条语句,而且不 能将它们直接嵌入到I/

16、O语句中去,显然使用起来不太方便。C+提供了另一种进行I/O格式 控制的方法,这一方法使用了一种称为操作符的特殊函数。 操纵符分为无参操纵符和带参操纵符,C+预定义的操纵符见表9.1。表9.2列出了常用带参操纵符。所有不带形参的操作符都定义在头文件iostream.h 中,而带形参的操作符则定义在头文件 iomaniph中,因而使用相应的操作符就必须包含相应的头文件。,19,表9.1 常用无参操纵符,20,表9.2 常用带参操纵符,21,例9-4操作符的使用例子 #include #include main() coutsetw(10)123546endl; cout123setiosflag

17、s(ios:scientific)setw(20)123.456789endl; cout123setw(10)hex123endl; cout123setw(10)oct123endl; cout123setw(10)dec123endl; coutresetiosflags(ios:scientific)setprecision(4)123.456789endl; coutsetiosflags(ios:left)setfill(,22,用户自定义的操作符 用户也可以自定义操纵符,其目的是合并程序中频繁使用的输入输出操作,使输入输出密集的程序变得更加清晰高效,并可能避免意外的 错误 若为输

18、出流定义的操纵符函数,其定义形式如下: ostream ,23,#include #include ostream ,24,#include #include istream,25,9.4 用户自定义类型的输入输出,前面介绍了系统预定义类型的输入输出。对于用户自定义类型的输入输出,可以通过重载运算符“”来实现。 对于任何给定的用户定义类型T,定义一个operator函数用于输出T类型的对象。运算符“”重载函数的一般格式为: ostream /操作代码 return stream; 其中函数中第一个参数是对ostream对象的引用,说明stream必须是输出流,且必须与return后面的标识符相

19、同,第二个参数是被输出的对象。,26,如果要访问类对象的私有部分,应在类的声明中将其声明为该类的友元函数。下面是对Point类重载插入运算符的例子。 class Point int x, y; public: Point(int a,int b):x(a),y(b) friend ostream ,27,提取运算符“”可以重载,由用户定义如何输入自定义的类对象。在重载提取运算符时,同样应将其重载为类的友元,而不是成员。对于任何给定的用户定义类型T,定义一个operator函数,用于从指定的输入流读取T类型的对象。输入运算符重载与输出运算符大体相同,只将osteam换为istream,把“”代替

20、即可。,28,9.5 文件的输入输出,在C+程序中使用的保存数据的文件按存储格式分为两种类型,一种为字符格式文件,简称字符文件,另一种为内部格式文件,简称字节文件。字符文件又称ASCII码文件或文本文件,字节文件又称二进制文件。在字符文件中,每个字节单元的内容为字符的ASCII码,被读出后能够直接送到显示器或打印机上显示或打印出对应的字符,供人们直接阅读。在字节文件中,文件内容是数据的内部表示,是从内存中直接复制过来的。当然对于字符信息,数据的内部表示就是ASCII码表示,所以在字符文件和在字节文件中保存的字符信息没有差别,但对于数值信息,数据的内部表示和ASCII码表示截然不同,所以在字符文

21、件和在字节文件中保存的数值信息也截然不同。,29,C+文件是一个字符流或二进制流,它把数据看作是一连串的字符,而不考虑记录的界限,它对文件的存取以字符为单位进行,将这种文件称为流式文件 在C+中,要进行文件的输入输出,必须先创建一个流,然后将这个流与文件相关联,即打开文件,此时才能进行读写操作,完成之后在关闭这个文件。,30,文件的打开与关闭 流可以分为3类:输入流、输出流以及输入/输出流,相应地文件流也有三个文件流:ifstream、ofstream以及fstream这些文件流都定义在fstream.h文件中: 要执行文件的输入输出,需要做3件事情: 在程序中包含头文件fstream.h。

22、建立流,建立流的过程就是定义流类的对象。例如 ifstream in; /说明一个输入流对象in ofstream out; /说明一个输出流对象out fstream both; /说明一个输入/输出流对象both 使用open()函数打开文件,也就是使某一个文件与上面的某一流向联系。Open函数是上述3个流类的成员函数,其函数原型在fstream.h中定义的,其原型为:,31,void open(const char * filename,int mode,int access=filebuf:openprot) 其中,filename是文件名字,它可包含路径说明。 mode说明文件打开的

23、模式,它对文件的操作影响重大,mode的取值必须是以下值之一: ios:in 打开文件进行读操作 ios:out 打开文件进行写操作 ios:ate 打开时文件指针定位到文件尾 ios:app 添加模式,所有增加都在文件尾部进行 ios:trunc 如果文件已存在则清空原文件 ios:nocreate 如果文件不存在则打开失败 ios:noreplace 如果文件存在则打开失败 ios:binary 二进制文件(非文本文件),32,下面对这些值作进一步说明 如果希望向文件尾部添加数据,则应当用“ ios:app”方式打开文件,但此时文件必须存在。打开时,文件位置指针移到文件尾部。用这种方式打开

24、的文件只能用于输出。 用“ios:ate”方式打开一个已存在的文件时,文件位置指针自动移到文件的尾部。 用“ios:in”方式打开的文件只能用于输入数据,而且该文件必须已经存在。如果用类ifstream来产生一个流,则隐含为输入流,不必再说明使用方式。用“ios:out”方式打开文件,表示可以向该文件输出数据。如果用类ofstream来产生一个流,则隐含为输出流,不必再说明使用方式。,33,通常,当用open()函数打开文件时,如果文件存在,则打开该文件,否则建立该文件。但当用“ios:nocreate”方式打开文件时,表示不建立新文件,在这种情况下,如果要打开的文件不存在,则函数open()

25、调用失败。相反,如果使用“ios:noreplace”方式打开文件。则表示不修改原来文件,而是要建立新文件。因此,如果文件已经存在,则open()函数调用失败。 当使用“ios:trunc”方式打开文件时,如果文件已存在,则清除该文件的内容,文件长度被压缩为0。实际上,如果指定“ios:out”方式,且未指定“ios:ate”方式或“ios:app”方式,则隐含为“ios:trunc”方式。 如果使用“ios:binary”方式,则以二进制方式打开文件,缺省时,所有的文件以文本方式打开。在用文本文件向计算机输入时,把回车和换行两个字符转换为一个换行符,而在输出时把换行符转换为回车和换行两个字符

26、。对于二进制文件则不进行这种转换,在内存中的数据形式与输出到外部文件中的数据形式完全一致,一一对应。,34,对于ifstream流,mode的默认值为ios:in;对于ofstream流,mode的默认值为ios:out。 access决定文件的访问方式,取值为: 0 普通文件 1 只读文件 2 隐含文件 4 系统文件 一般情况下,该访问方式使用默认值为filebuf:penprot。 与其他状态标志一样,mode的符号常量可以用位或运算“|”组合在一起,如ios:in|ios:binary表示以只读方式打开二进制文件。 文件的关闭: out.close():将关闭与流out相联接的文件。,3

27、5,文件的读写 文本文件只适用于那些解释为ASCII码的文件。处理文本文件时将自动作一些字符转换,如输出换行字符0x0A时将转换为回车0x0D与换行0x0A两个字符存入文本文件,读入时也会将回车与换行两个字符合并为一个换行字符,这样内存中的字符与写入文件中的字符之间就不再是一一对应关系。文本文件的结束以ASCII码的控制字符0x1A表示。 一旦文件打开,从文件中读出数据与向文件中写入数据都十分容易,只需要使运算符“”就可以了,但不必须用与文件相关联的流代替cin和cout。 例9-9给出将数据写入文件test中。,36,#include void main() ofstream fout(“t

28、est”); if(!fout)cout“Cannot open output filen”; return 1; fout10“ “123.456“” This is a text file.”n”; fout.close(); 例9-12给出了先建立一个输出文件,向它写入数据,然后关闭文件,再按输入方式打开它并读取信息,37,#include int main() ofstream fout(“test2“); if(!fout) coutstri; coutstr“ “iendl; fin.close(); return 0;,38,二进制文件的读写 二进制文件不同于文本文件,它可用于任

29、何类型的文件(包括文本文件),读写二进制文件的字符不作任何转换,读写的字符与文件之间是完全一致的。 一般地,对二进制文件的读写可采用两种方法:一种是使用get()和put();另一种是使用read()和write()。 1. get()与put()函数的一般格式: istream &get(unsigned char &ch) get()函数从相关流中只读一个字符,并把该值放入引用ch&中 ostream &put(char ch) put()函数将字符ch写入流中 2. read()与write()函数的一般格式: istream &read(unsigned char *buf,int n

30、um) read()函数从相应的流中读取num个字节,并把它放入指针buf所指的缓冲区中 ostream &write(const unsigned char *buf,int num) write()函数把buf所指的缓冲区中的num,39,例9.11给出了put()与get()函数的用法。 #include #include void test_write() ofstream fs (“d: test.dat“); int i; char c=a; for(i=0;i26;i+) fs.put(c); c+; void test_read() ifstream fs (“d: test.

31、dat“); char c; while(fs.get(c) coutc; void main() test_write(); test_read();,40,例9.12与9.13给出了write()函数与read()函数的使用情况 #include #include #include main() ofstream out(“test2“); if(!out) cout“Cannot open output filen“; return 1; int i=12340; double num=100.45; out.write(char *) ,41,#include #include #in

32、clude main() ofstream in(“test2“); if(!in) cout“Cannot open output filen“; return 1; int i;double num; in.write(char *) ,42,文件的随机读写 输出流随机访问函数。 输出流随机访问函数有seekp ostream 在上面函数参数中,类型streampos和streamoff都等效于long类型,包含在iostream.h文件中,分别限定了文件的位置以及操作的相对偏移的范围。其中dir表示文件指针的起始位置,off表示相对于起始位置的位移量。dir的取值有以下三种情况: ios

33、:beg 从文件头开始,把文件指针移动由off指定的距离 ios:cur 从当前位置开始,把文件指针移动由off指定的距离 ios:end 从文件尾开始,把文件指针移动由off指定的距离 函数seekg()用于输入文件,将相应文件的读指针从dir说明的位置移动off个字节;函数seekp()用于输出文件,将相应文件的写指针从dir说明的位置移动off个字节,43,例子9.14 #include #include void main(void) fstream fs; fs.open(“F: test“,ios:in| ios :out); if(fs.fail() cout“open file errer!“; else fs.seekp(4,ios:beg); fs.put(X); char contents10; fs.seekg(4,ios:beg); fs.get(contents,10); coutcontents; ,44,进行文件的随机读写时,可以用以下函数确定每个文件指针的当前位置: streampos tellg(); streampos tellp(); 其中tellg()函数用于输入文件,tellp()函数用于输出文件,45,本章作业 重点复习本书的三、四、五、六与七章的内容,

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

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1