第10章流类库与输入输出.ppt

上传人:sccc 文档编号:5887001 上传时间:2023-08-29 格式:PPT 页数:61 大小:384.04KB
返回 下载 相关 举报
第10章流类库与输入输出.ppt_第1页
第1页 / 共61页
第10章流类库与输入输出.ppt_第2页
第2页 / 共61页
第10章流类库与输入输出.ppt_第3页
第3页 / 共61页
第10章流类库与输入输出.ppt_第4页
第4页 / 共61页
第10章流类库与输入输出.ppt_第5页
第5页 / 共61页
点击查看更多>>
资源描述

《第10章流类库与输入输出.ppt》由会员分享,可在线阅读,更多相关《第10章流类库与输入输出.ppt(61页珍藏版)》请在三一办公上搜索。

1、1,第10章 流类库与输入输出,10.1 流、文件以及C+的基本流类和文件流类系统*10.2 插入与提取运算符的重载10.3 对输入输出格式进行控制10.4 使用预定义的插入与提取运算符对文件流进行读写操作10.5 使用类成员函数对文件流进行操作10.6 text文件与binary文件10.7 对数据文件进行随机访问,2,10.1 流、文件以及C+的基本流类和文件流类系统-参看书p232-234,10.2与10.3节,C+语言中的输入输出操作(功能)是由它所预定义的诸I/O流类的一个类库所提供的。1.流(Stream)流(stream)是一个逻辑概念,它是C+语言对所有外部设备的逻辑抽象,它代

2、表的是某种流类类型的一个对象。C+的IO系统将每个外部设备都转换成一个称为流的逻辑设备,由流来完成对不同设备的具体操作。,3,2.文件(File),文件(File)是一个物理概念,代表存储着信息集合的某个外部介质,它是C+语言对具体设备的抽象。如,磁盘文件,显示器,键盘。所有流(类对象)的行为都是相同的,而不同的文件则可能具有不同的行为。如,磁盘文件可进行写也可进行读操作;显示器文件则只可进行写操作;而键盘文件只可进行读操作。当程序与一个文件交换信息时,必须通过“打开文件”的操作将一个文件与一个流(类对象)联系起来。一旦建立了这种联系,以后对该流(类对象)的访问就是对该文件的访问,也就是对一个

3、具体设备的访问。可通过“关闭文件”的操作将一个文件与流(类对象)的联系断开。,4,3.C+的基本流类系统 在头文件“iostream.h”中说明(预定义)了一批基本流类:ios-基本流类的基类;istream-由ios派生,支持输入(提取“”)操作;ostream-由ios派生,支持输出(插入“”)操作;iostream-由istream与ostream共同派生,支持输入和输出双向操作。,5,C+预定义的流有:extern istream cin;-对象cin对应于键盘文件 extern ostream cout;-对象cout对应于显示器文件 extern ostream cerr;-对象c

4、err对应于显示器文件 extern ostream clog;-对象clog对应于显示器文件 程序中可直接对上述4个预定义流类对象进行读写,而不必先进行“打开文件”的操作,使用完后也不需要进行“关闭文件”的操作(因为这些流类对象与文件之间的联系是预定义好的,可认为系统已为每一程序都隐含进行了对它们的打开与关闭操作)。,6,4.C+的文件流类系统 在头文件“fstream.h”中说明(预定义)了一批文件流类,专用于磁盘文件:ifstream-由istream派生,支持从磁盘文件中输入(读入)数据;ofstream-由ostream派生,支持往磁盘文件中输出(写出)数据;fstream-由ios

5、tream派生,支持对磁盘文件进行输入和输出数据的双向操作。C+中没有预定义的文件流(类对象),程序中用到的所有文件流类对象都要进行自定义。,7,*10.2 插入与提取运算符的重载-参看书p231,10.1节后半,对自定义类complex重载输入输出运算符“”:#includeclass complex double r;double i;public:complex(double r0=0,double i0=0)r=r0;i=i0;complex operator+(complex c2);complex operator*(complex c2);friend istream,8,注意:

6、1.通常总以友元方式来重载输入输出运算符,而且大都使用类似于上述的重载格式。2.其中的“operator”用于完成从istream类的流类对象in上(如对应实参可为cin,即指定从键盘上)输入一个复数的有关数据放入complex型引用对象com中;而“operatorc1c2;”这样的调用语句。另外,“operator”的第二形参com也必须被说明成引用“complex&com”,目的则是要将输入数据直接赋值给对应实参变量(所拥有的存储空间中)。,9,complex complex:operator+(complex c2)complex c;c.r=r+c2.r;c.i=i+c2.i;ret

7、urn c;complex complex:operator*(complex c2)complex temp;temp.r=(r*c2.r)-(i*c2.i);temp.i=(r*c2.i)+(i*c2.r);return temp;,10,istream,11,coutc3;coutc3;”则等同于使用“operator(cin,c3);”。*/程序执行后,屏幕显示结果为:c1=(1,1)c2=(2,3)c1+c2=(3,4)c1*c2=(-1,5)Input c3:3-5c3+c3=(6,-10),12,10.3 对输入输出格式进行控制10.3.1 格式控制函数及格式控制符 10.3.2

8、 输入输出格式控制示例,13,10.3.1 格式控制函数及格式控制符-参看书p234,10.4节,1.ios类中常用的公有格式控制成员函数 在ios类中定义了一批公有的格式控制标志位以及一些成员函数,通常先用某些成员函数来设置标志位,然后再使用另一些成员函数来进行格式输出。另外,ios类中还设置了一个long型的数据成员用来记录当前被设置的格式状态,该数据成员被称为格式控制标志字(或标志状态字)。标志字是由格式控制标志位来“合成”的。注意,ios类作为诸多I/O流类的基类,其公有成员函数当然可被各派生类的对象所直接调用。,14,(1)ios:flags a.格式一:long flags(lon

9、g lFlags);通过参数lFlags来重新设置标志字。表示各标志位的枚举常量有(参看p235):ios:skipwsios:left ios:right.ios:stdio 每一枚举常量值都代表着格式控制标志字中的某一个二进制位(bit),当设置了某个标志位属性时,该位将取值“1”,否则该位取值“0”。,15,另外注意,通过使用位运算符“|”可将多个格式控制标志位属性进行“合成”。但从使用角度看,所设置的标志位属性不能产生互斥。例如,格式控制标志字中设立了三个平行的标志位(ios:dec、ios:oct和ios:hex)用于表示数制,程序员应保障任何时刻只设置其中的某一个标志位。还有表示对

10、齐标志位的ios:left、ios:right和ios:internal,以及表示实数格式标志位的ios:scientific和ios:fixed,这些互斥属性也不能同时设置。b.格式二:long flags();返回当前的标志字。,16,(2)ios:setf a.格式一:long setf(long lFlags);通过参数lFlags来设置指定的格式控制标志位。注意,与flags函数的“替换”方式不同,此处为“添加”方式,即是说,它并不更改其它lFlags不涉及到的那些标志位的当前值。b.格式二:long setf(long lFlags,long lMask);设置指定的格式控制标志位

11、的值(首先将第二参数lMask所指定的那些位清零,而后用第一参数lFlags所给定的值来重置这些标志位)。,17,例如,为保障所设置的数制标志位不产生互斥,当要设置16进制时使用:setf(ios:hex,ios:basefield);其中的ios:basefield为一个在ios类中定义的公有静态常量,它的取值为ios:dec|ios:oct|ios:hex。同理,当要设置对齐标志位为ios:right以及实数格式标志位为ios:fixed,要使用:setf(ios:right,ios:adjustfield);setf(ios:fixed,ios:floatfield);其中用到了公有静态

12、常量ios:adjustfield和ios:floatfield。ios:adjustfield的取值为ios:left|ios:right|ios:internal,而ios:floatfield的取值为ios:scientific|ios:fixed。,18,(3)ios:unsetf long unsetf(long lFlags);通过参数lFlags来清除指定的格式控制标志位。(4)ios:fill char fill(char cFill);将“填充字符”设置为cFill,并返回原“填充字符”。,19,(5)ios:precision int precision(int np);设

13、置浮点数精度为np并返回原精度。当格式为ios:scientific或ios:fixed时,精度np指小数点后的位数,否则指有效数字。(6)ios:width int width(int nw);设置当前被显示数据的域宽nw并返回原域宽。默认值为0,将按实际需要的域宽进行输出。此设置只对随后的一个数据有效,而后系统立刻恢复域宽为系统默认值0。,20,2.常用的输入输出格式控制符 可直接用于提取和插入算符(“”和“”)之后,而不像格式控制成员函数那样必须被单独调用。(1)iostream.h中含有的无参格式控制符(参看p237):.endl.ends.flush.ws.dec.hex.oct,2

14、1,(2)iomanip.h中含有的有参格式控制符(参看p237):.setbase(int base).resetiosflags(long lFlags).setiosflags(long lFlags).setfill(char cFill).setprecision(int np).setw(int nw),22,10.3.2 输入输出格式控制示例,1.格式控制示例一(flags和setf等函数的功能)#include void main()coutios basefield;/输出:112 cout(ios:dec|ios:oct|ios:hex)endl;/输出:112 couti

15、os:adjustfield;/输出:14 cout(ios:left|ios:right|ios:internal)endl;/输出:14 coutios:floatfield;/输出:6144 cout(ios:scientific|ios:fixed)endl;/输出:6144,23,/flags将重新设置标志字,“替换”方式 cout.flags(ios:showbase);coutcout.flags()endl;/输出:128 cout.flags(ios:showpoint);coutcout.flags()endl;/输出:256 cout.unsetf(ios:showpoi

16、nt);coutcout.flags()endl;/输出:0/setf为“添加”方式 cout.setf(ios:showbase);coutcout.flags()endl;/输出:128 cout.setf(ios:showpoint);coutcout.flags()endl;/输出:384 cout.unsetf(ios:showpoint);coutcout.flags()endl;/输出:128,24,2.格式控制示例二 对输出数据的宽度、精度等方面进行设置与使用。#include void main()cout.width(6);/只管随后一个数的域宽 cout478527.42

17、72endl;/478527.4272coutsetw(6)4785setw(8)27.4272endlendl;/4785 27.4272cout.width(6);cout.precision(3);/当格式为ios:scientific或ios:fixed时,浮点数精度/np指小数点后的位数,否则指有效数字/此时设置浮点数的有效数字为3cout4785setw(8)27.4272endl;/4785 27.4,25,coutsetw(6)4785setw(8)setprecision(2)27.4272endlendl;/4785 27/“setprecision(2)”设置浮点数的有效

18、数字cout.setf(ios:fixed,ios:floatfield);/今后以定点格式显示浮点数(无指数部分)cout.width(6);cout.precision(3);/当格式为ios:fixed时,设置小数点后的位数cout4785setw(8)27.4272endl;/4785 27.427,26,10.4 使用预定义的插入与提取运算符对文件流进行读写操作10.4.1 文件的打开与关闭10.4.2 读写操作示例 10.4.1 文件的打开与关闭-参看书p244,10.6.1小节 一.对自定义磁盘文件进行读写的一般处理过程 处理过程为:打开文件=读写操作=关闭文件。,27,“打开文

19、件”通常通过构造函数自动完成(也可显式调用成员函数open完成)。“关闭文件”通常通过使用“.close();”来显式完成。例1:ofstream outfile1(myfile1.txt);创建ofstream类的对象outfile1;使流类对象outfile1与磁盘文件myfile1.txt相联系;并打开用于“写”的磁盘文件myfile1.txt。例2:ofstream outfile1;/创建ofstream类的对象outfile1 outfile1.open(myfile1.txt);/显式调用成员函数open来打开文件,28,二.与创建流类对象相关的三个构造函数 1.ifstream

20、:ifstream ifstream(const char*szName,int nMode=ios:in,int nProt=filebuf:openprot);参数:(1)szName-文件名;(2)nMode-打开文件的方式。ios:in-以读(输入)为目的打开。ios:nocreate-仅打开一个已存在文件。ios:binary-打开二进制文件。(3)nProt-指定所打开文件的保护方式。,29,2.ofstream:ofstream ofstream(const char*szName,int nMode=ios:out,int nProt=filebuf:openprot);参数:

21、(1)szName-文件名;(2)nMode-打开文件的方式。ios:out-以写(输出)为目的打开文件。ios:trunc-若文件存在,则将文件长度截为0。ios:binary-打开二进制文件。ios:app-以追加方式打开。.(3)nProt-指定所打开文件的保护方式。,30,3.fstream:fstream fstream(const char*szName,int nMode,int nProt=filebuf:openprot);参数含义和用法与ofstream构造函数处相同。三.与创建流类对象相关的三个open函数 1.ofstream:open void open(const

22、char*szName,int nMode=ios:out,int nProt=filebuf:openprot);2.ifstream:open void open(const char*szName,int nMode=ios:in,int nProt=filebuf:openprot);3.fstream:open void open(const char*szName,int nMode,int nProt=filebuf:openprot);,31,10.4.2 读写操作示例-参看书p246,10.6.2小节的1,对文件的“读写操作”通常使用预定义的类成员函数来实现(随后介绍),但也

23、可使用继承而来的插入和提取运算符“”和“”,所以,ifstream流(类对象)可以使用预定义的算符“”来对自定义磁盘文件进行“读”操作(允许通过派生类对象直接调用其基类的公有成员函数);ofstream类由ostream类所派生,而ostream类中预定义了公有的运算符重载函数“operator”,所以,ofstream流(类对象)可以使用预定义的算符“”来对自定义磁盘文件进行“写”操作;,32,fstream类由iostream所派生,iostream类由istream与ostream类共同派生,所以,fstream流(类对象)可以使用预定义的算符“”和“”来进行“读”操作时遇空格或换行均结

24、束一个数据相呼应。下述示例程序做了如下的3件事:1)往文件写数据;2)往文件尾部追加数据;3)从文件读出数据并显示在屏幕上。,33,#include void main()/1)往文件写数据ofstream outfile1(myfile1.txt);/以“写”方式打开outfile1str1str2;/使用“”读(遇空格、换行均结束)infile1x2y2;infile1.close();,34,coutstr1=str1endl;coutstr2=str2endl;coutx2=x2endl;couty2=y2endl;程序执行后的显示结果如下:str1=Hello!.CHINA!str2

25、=Nankai_Universityx2=1212y2=6868,35,10.5 使用类成员函数对文件流进行操作10.5.1 类成员函数get与put10.5.2 类成员函数read与write10.5.3 类成员函数getline,36,10.5.1 类成员函数get与put-参看书p247,10.6.2小节的2,ostream功能:从自定义文件中读出1个字符放入引用rch中。注意,put实际上只是ostream类中定义的公有成员函数,当然通过其派生类ofstream的类对象也可以直接对它进行调用。同理,通过ifstream的类对象可以直接调用get。,37,1.程序示例一 从键盘输入任一个

26、字符串,通过put将其写到自定义磁盘文件“putgetfile.txt”中,而后再使用get从该文件中读出所写串并显示在屏幕上。#include#include void main()/键盘输入字符串,通过put将其写到自定义磁盘文件中char str80;coutInput string:endl;gets(str);ofstream fout(putgetfile.txt);int i=0;while(stri)fout.put(stri+);fout.close();cout-endl;,38,/而后使用get从文件中读出该串显示在屏幕上char ch;ifstream fin(putg

27、etfile.txt);fin.get(ch);while(!fin.eof()/从头读到文件结束(当前符号非文件结束符时继续)/注:成员函数eof()在读到文件结束时方返回true coutch;fin.get(ch);coutendl;fin.close();程序执行后的显示结果如下:Input string:File operating-using put and get,OK!12345-File operating-using put and get,OK!12345,39,2.程序示例二-对指定文件进行拷贝 使用类成员函数get与put对指定文件进行拷贝。被拷贝的“源文件”以及拷贝

28、到的“目的文件”的名字与路径均由命令行参数来提供。程序执行结果(若提供的命令行参数为:mycopy.cpp res_1.cpp):Copy file from mycopy.cpp to res_1.cpp 程序执行结果(若提供的命令行参数个数不对时):ERROR!-supplying 2 command-line argements?!,40,#include#include void main(int argc,char*argv)if(argc!=3)/命令行参数个数不对时 coutERROR!-supplying 2 command-line argements?!endl;exit(

29、1);coutCopy file from argv1 to argv2endl;ifstream fin(argv1);/命令行参数1作为文件名 ofstream fout(argv2);/命令行参数2作为文件名 char ch;fin.get(ch);while(!fin.eof()/从头读到文件结束 fout.put(ch);fin.get(ch);fin.close();fout.close();,41,10.5.2 类成员函数read与write-参看书p247,10.6.2小节的2,通常使用read与write对二进制文件(binary file)进行读写。ostream 功能:从

30、某个文件中读入nCount个字符放入pch缓冲区中(若读至文件结束尚不足nCount个字符时,也将立即结束本次读取过程)。注意:使用write与read进行数据读写时,不必要在数据间再额外“插入”分割符,这是因为它们都要求提供第二实参来指定读写长度。,42,以下的示例程序先使用write往自定义二进制磁盘文件中写出如下3个“值”:字符串str的长度值Len(一个正整数)、字符串str本身、以及一个结构体的数据,而后再使用read读出这些“值”并将它们显示在屏幕上。#include#include void main()char str20=Hello world!;struct stuchar

31、 name20;int age;double score;ss=wu jun,22,91.5;,43,coutWRITE to wrt_read_file.binendl;ofstream fout(wrt_read_file.bin,ios:binary);/打开用于“写”的二进制磁盘文件int Len=strlen(str);fout.write(char*)(,44,fin.read(char*)(程序执行后的显示结果如下:WRITE to wrt_read_file.bin-READ it from wrt_read_file.bin-Len=12str2=Hello world!ss

32、=wu jun,22,91.5-,45,最常用格式为:istream 功能:从某个文件中读出一行(至多nCount个字符)放入pch缓冲区中,缺省行结束符为n。程序实例:读出“getline_1.cpp”的各行并显示在屏幕上(如,可将本源程序存放在“getline_1.cpp“文件中)。,10.5.3 类成员函数getline-注,书中没介绍该函数,46,#include void main()char line81;ifstream infile(“getline_1.cpp”);/打开文件用于读 infile.getline(line,80);/读出一行(至多80个字符)放入line中 w

33、hile(!infile.eof()/尚未读到文件结束则继续循环(处理)coutlineendl;/显示在屏幕上 infile.getline(line,80);/再读一行 infile.close();,47,10.6 text文件与binary文件10.6.1 对text文件与binary文件的一般使用示例10.6.2 采用binary文件形式对结构体数据进行存储与读写处理-10.6.1 对text文件与binary文件的一般使用示例*以text形式存储,优点是具有较高的兼容性。缺点是存储一批纯数值信息时,要在数据之间人为地添加分割符;输入输出过程中,系统要对内外存的数据格式进行相应转换;

34、另外text文件不便于对数据实行随机访问。,48,*以binary形式存储,优点是便于对数据实行随机访问(每一同类型数据所占磁盘空间的大小均相同,不必在数据之间人为地添加分割符);输入输出过程中,系统不对数据进行任何转换。缺点是兼容性低。注:由程序员决定将数据存储为text文件或者binary文件两种形式之一。缺省打开方式时,默认为text文件形式。若欲使用binary文件形式,要将打开方式设为“ios:binary”。通常将纯文本信息(如字符串)以text文件形式存储,而将数值信息以binary文件形式存储。,49,1.示例1-对两种文件进行操作 将a数组中准备好的8个int型数据,分别通过

35、算符“”依次写出到text文件ft.txt之中(注意各数据在文件中“长短”不一,且数据间必须加入分割符)。而且还通过使用类成员函数write将这相同的8个int型数据依次写出到binary文件fb.bin之中(注意各数据在文件中“长短”相同,且数据间不需要加入分割符)。另外,程序中通过使用无参的成员函数“tellp()”来获取当前已写出到各文件的位置信息,以确认每一数据在文件中所占的字节数。ostream:tellp之功能为:获取并返回“输出指针”的当前位置值(从文件首到当前位置的字节数)。,50,#include void main()int a8=0,1,-1,1234567890;for

36、(int i=4;i8;i+)ai=876543210+i-4;/均由9位数字组成,在text文件中所占字节数也为9 ofstream ft(ft.txt);ofstream fb(fb.bin,ios:binary);for(i=0;i8;i+)ftai;/数据间需要添加分割符 fb.write(char*)(,51,程序执行后的输出结果如下:ft.tellp()=2,fb.tellp()=4ft.tellp()=4,fb.tellp()=8ft.tellp()=7,fb.tellp()=12ft.tellp()=18,fb.tellp()=16ft.tellp()=28,fb.tellp(

37、)=20ft.tellp()=38,fb.tellp()=24ft.tellp()=48,fb.tellp()=28ft.tellp()=58,fb.tellp()=32,52,*2.示例2-使用read与write对text文件进行操作时可能出错 具体程序从略。评注:(1)通常使用read与write对二进制文件进行操作,但若非要使用它们对文本文件进行操作时,系统在write时有可能多写出了一些东西(如,回车换行符号等)。这样将导致read时产生错误。(2)read与write功能的进一步解释:istream:read Extracts bytes from the stream until

38、 the limit nCount is reached or until the end of file is reached.The read function is useful for binary stream input.ostream:write Inserts a specified number of bytes from a buffer into the stream.If the underlying file was opened in text mode,additional carriage return characters may be inserted.Th

39、e write function is useful for binary stream output.,53,10.6.2 采用binary文件形式对结构体 数据进行存储与读写处理,从键盘读入多个结构数据(个数n由用户指定),使用write将这些结构数据写出到某个自定义二进制磁盘文件中,而后再使用read读出这些结构数据并进行处理(如,求出n个score的平均值ave)。#include void main()struct person char name 20;int age;float score;ss;int n;cinn;/个数n由用户指定,54,ofstream fout(f01.

40、bin,ios:binary);/打开二进制文件(写)for(int i=0;iss.namess.agess.score;fout.write(char*)(,55,10.7 对数据文件进行随机访问-参看书p248,10.6.2小节的3,使用类成员函数write与read,并配合使用类成员函数seekp和seekg,就可以对文件进行“随机性”(非顺序性)的读写操作。1)ostream:seekp ostream 功能:将“输出指针”的值置到一个新位置,使以后的输出从该新位置开始。新位置由参数off与dir之值确定:-当dir之值为“ios:beg”时,新位置为:从文件首“后推”off字节处;

41、-当dir之值为“ios:cur”时,新位置为:从“输出指针”的当前位置“后推”off字节处;-当dir之值为“ios:end”时,新位置为:从文件末“前推”off字节处。,56,2)istream:seekg istream 功能:获取“输出指针”的当前位置值。,57,1.示例1 从键盘输入10个int型数,而后按输入的相反顺序输出它们。实现方法:使用binary文件,将数据存放在文件中,并使用随机访问方式读出。#include void main()const int n=10;int x,i;ofstream fout(fdat.bin,ios:binary);coutx;fout.wr

42、ite(char*)(,58,cout=0;i-)fin.seekg(i*sizeof(int);fin.read(char*)(程序执行后的输出结果为:Input 10 integers:1 2 3 4 5 6 7 8 9 10-The result-10 9 8 7 6 5 4 3 2 1,59,*2.示例2(作为参考):使用write将多个person类型的结构体数据,写出到某个自定义二进制磁盘文件的指定位置处,而后再使用read从另外指定的位置处读出某些结构体数据并显示在屏幕上。一般程序处理模式:struct person char name 20;int age;.ss;int recnum;,60,ofstream fout(f01.bin,ios:binary);while(需要继续写出)形成欲写出的结构体ss;形成recnum;/“纪录号”,如下标号,位置含义 long offs=sizeof(ss)*(recnum-1);fout.seekp(offs);fout.write(char*)(,第十章 结束,

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

当前位置:首页 > 建筑/施工/环境 > 农业报告


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号