1 / 63

第 9 章 流类库与输入 / 输出

第 9 章 流类库与输入 / 输出. 教学内容: I/O 流类库的功能,常用的读写操作,格式化输入输出操作,插入符和提取符的重载,磁盘文件的输入和输出操作,字符串流操作。 教学要求: 理解文件流的打开、读写、关闭方法以及设备文件的使用 ; 掌握基本输入 / 提取操作和格式控制。. 第 9 章 流类库与输入 / 输出. 9.1 输入 / 输出标准流类 9.2 文件流类 9.3 串流类 9.4 控制符. 9.1 输入 / 输出标准流类. 9.1.1 输入 / 输出流的概念

kieve
Download Presentation

第 9 章 流类库与输入 / 输出

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第9章 流类库与输入/输出 • 教学内容: • I/O流类库的功能,常用的读写操作,格式化输入输出操作,插入符和提取符的重载,磁盘文件的输入和输出操作,字符串流操作。 • 教学要求: • 理解文件流的打开、读写、关闭方法以及设备文件的使用; • 掌握基本输入/提取操作和格式控制。

  2. 第9章 流类库与输入/输出 • 9.1 输入/输出标准流类 • 9.2 文件流类 • 9.3 串流类 • 9.4 控制符

  3. 9.1 输入/输出标准流类 • 9.1.1 输入/输出流的概念 • C++语言中没有输入/输出语句。C++的I/O是以字节流的形式实现的,每一个C++编译系统都带有一个面向对象的输入/输出软件包,这就是I/O流类库。其中,流是I/O流类的中心概念。到目前为止,我们一直在使用它。

  4. 所谓流,是指数据从一个对象流向另一个对象。在C++程序中,数据可以从键盘流入到程序中,也可以从程序中流向屏幕或磁盘文件,把数据的流动抽象为“流”。流在使用前要被建立,使用后要被删除,还要使用一些特定的操作从流中获取数据或向流中添加数据。从流中获取数据的操作称为提取操作,向流中添加数据的操作称为插入操作。所谓流,是指数据从一个对象流向另一个对象。在C++程序中,数据可以从键盘流入到程序中,也可以从程序中流向屏幕或磁盘文件,把数据的流动抽象为“流”。流在使用前要被建立,使用后要被删除,还要使用一些特定的操作从流中获取数据或向流中添加数据。从流中获取数据的操作称为提取操作,向流中添加数据的操作称为插入操作。

  5. 流实际上就是一个字节序列。在输入操作中,字节从输入设备(如键盘、磁盘、网络连接等)流向内存;在输出操作中,字节从内存流向输出设备(如显示器、打印机、磁盘、网络连接等)。如图9-1所示。 在C++语言中,针对流的特点,提供了如图9-2所示的层次结构来描述流的行为,并给出了I/O流类库的操作。

  6. 图9-2 输入/输出流类层次图

  7. 表9-1 I/O流类列表

  8. 9.1.2 输入/输出标准流类 • 1.标准流的设备名 • 由表9-1可见,I/O流的标准头文件是iostream.h。其中,ostream类通过其派生类ostream_withassign支持以下预先定义的流对象: • cout:标准输出。默认设备为屏幕。 • cerr:标准错误输出。没有缓冲,发送给它的内容立即被输出,默认设备为屏幕。

  9. clog:标准错误输出。有缓冲,当缓冲区满时被输出,默认设备为打印机。 • 而istream类通过其派生类istream_withassign支持预先定义的对象。 • cin:标准输入。默认设备为键盘。

  10. 2.原理 • cout是ostream类的全局对象,它在头文件iostream.h中的定义如下: • ostream cout(stdout); //这里,stdout作为该对象构造时的参数对应每种基本数据类型,ostream类都存在友元,它们都在iostream.h中声明。例如: • ostream& operator<<(int n); • ostream& operator<<(float f); • ostream& operator<<(const char*psz); • //...

  11. 如语句: • cout<<"How old are you? "; • cout是类ostream的对象,<<是插入运算符,右面是char*类型,所以,应该匹配上面第三个操作符。它将整个字符串输出,并返回ostream流对象的引用。 • 同理,cin是istream的全局对象,istream类也存在友元。例如: • istream& operator>>( int &n); • istream& operator>>( float &f); • istream& operator>>( char*psz); • //...

  12. 9.2 文件流类 • fstream、ifstream和ofstream是文件流类,在头文件fstream.h中定义。其中,fstream是ofstream和ifstream多重继承的子类。文件流类不是标准设备,没有cout那样预先定义的全局对象。文件流类支持对磁盘文件的操作。要定义一个文件流类对象,须指定文件名和打开方式。

  13. 类ofstream用于执行文件输出,该类有以下几个构造函数:类ofstream用于执行文件输出,该类有以下几个构造函数: • ofstream::ofstream( filedesc fd ); • ofstream::ofstream( filedesc fd, char*pch, int nLength ); • ofstream::ofstream( const char*szName, • int nMode = ios::out, • int nProt = filebuf::openprot );

  14. 类ifstream用于执行文件输入,该类有以下几个构造函数:类ifstream用于执行文件输入,该类有以下几个构造函数: • ifstream::ifstream( filedesc fd ); • ifstream::ifstream( filedesc fd, char*pch, int nLength ); • ifstream::ifstream( const char*szName, • int nMode = ios::in, • int nProt = filebuf::openprot );

  15. 其中最常用的都是最后一个构造函数。该函数有三个参数,第一个参数是指向要打开的文件名的字符串,后两个参数指定文件的打开模式。文件打开模式的具体标志见表9-2。可以用按位OR(|)运算符组合这些标志,它们作为枚举器定义在ios类中。其中最常用的都是最后一个构造函数。该函数有三个参数,第一个参数是指向要打开的文件名的字符串,后两个参数指定文件的打开模式。文件打开模式的具体标志见表9-2。可以用按位OR(|)运算符组合这些标志,它们作为枚举器定义在ios类中。

  16. 表9-2 文件打开模式

  17. 打开一个输出文件,用于在文件尾添加数据 • 打开一个现存文件(用于输入或输出)并查找到结尾 • 打开一个输入文件。对于一个ofstream文件,使用ios::in作为一个openmode,可避免删除一个现存文件中现有的内容 • 打开一个文件,用于输出。对于所有ofstream对象,此模式是隐含指定的 • 如果一个文件存在,则打开它;否则该操作失败

  18. 如果一个文件不存在,则作为新文件打开它;如果文件已存在,则该操作失败如果一个文件不存在,则作为新文件打开它;如果文件已存在,则该操作失败 • 打开一个文件。如果它已经存在,则删除其中原有的内容。如果指定了ios::out,但没有指定ios::ate、ios::app和ios::in,则隐含为此模式 • 以二进制模式打开一个文件(默认是文本模式) • Nprot是文件保护方式,它的标志如表9-3。

  19. 表9-3 文件保护方式

  20. 【例9-1】 向文件myfile中写入一些信息。 • #include<fstream.h> • void main( ) • { • ofstream fc("c:\\temp\\myfile"); • fc<<"Constructs an ofstream object.\n" • <<"All ofstream constructors construct a filebuf object. \n"; • }

  21. 注意: • ① 这里的文件名要说明其路径,要使用双斜杠,因为C++编译器理解单斜杠为字符转换符。 • ② 在文件打开时,匹配了构造函数ofstream::ofstream(char*),只需要一个文件名,其它为默认。打开方式默认为ios::out | ios::trunc,即该文件用于接受程序的输出。如果该文件已存在,则其内容必须先清除,否则就新建。

  22. 如果要检查文件是否打开,则须判断成员函数fail( ): • #include <fstream.h> • void func( ) • { • ofstream fc("myfile"); • if(fc.fail( )) //fail( )= =1 • { • cerr<<"error opening file\n"; • return; • } • fc<<"...";

  23. } • 若要打开一个输入文件,则有 • //... • ifstream fc("myfile",ios::nocreate); • //... • 当然,也可以通过检查fc.fail( )来确定文件打开是否出错。 • 如果要打开一个同时用于输入和输出的文件,则有 • //... • fstream fc("myfile",ios::in | ios::out); • //...

  24. 9.3 串流类 • strstream、istrstream和ostrstream是串流类,在头文件strstrea.h中定义。其中,strstream是istrstream和ostrstream多重继承的子类。同样,串流类也不是标准设备,它没有cout那样预先定义的全局对象。串流类允许将fstream类定义的文件操作应用于存储区中的字符串,即将字符串看作为设备。要定义一个串流类对象,须提供字符数组和数组大小。

  25. 类ostrstream用于执行串流输出,该类有以下几个构造函数:类ostrstream用于执行串流输出,该类有以下几个构造函数: • ostrstream( ); • ostrstream( char*pch, int nLength, int nMode = ios::out ); • 其中比较常用的是第二个构造函数,它有三个参数。第一个参数指出字符数组,第二个参数说明数组的大小,第三个参数指出打开方式。

  26. 类istrstream用于执行串流输入,该类有以下几个构造函数:类istrstream用于执行串流输入,该类有以下几个构造函数: • istrstream( char*pch ); • istrstream( char*pch, int nLength ); • 这两个构造函数都比较常用。Char*pch参数指出了字符数组,int nLength参数说明数组的大小。当nLength为0时,表示把istrstream类对象连接到由pch指向的以空字符结束的字符串。

  27. 例如,下面的程序代码定义一个串流类对象,并对其进行输入操作:例如,下面的程序代码定义一个串流类对象,并对其进行输入操作: • char str[50]="How are you!\n"; • char a; • istrstream ss(str); • ss>>a; • cout<<a<<endl; • 输出结果为 • H

  28. 【例9-2】 使用串流输入对字符串中的数据进行解读。 • #include<iostream.h> • #include<strstrea.h> • char *ioString(char*); • void main( ) • { • char *str="100 123.456"; • char *Buf0=ioString(str); • cout<<Buf0<<endl; • }

  29. char *ioString(char *pString) • { • istrstream inS(pString,0); //以ios::in方式 • int iNumber; • float fNumber; • inS>>iNumber>>fNumber; //从串流中读入一个整数和浮点数 • char*Buf1=new char[28]; • ostrstream outS(Buf1,28); • outS<<"iNumber="<<iNumber • <<",fNumber="<<fNumber<<endl; • return Buf1;

  30. } • 程序运行结果为 • iNumber=100,fNumber=123.456 • 分析:在函数ioString( )中,以pString为输入设备,先定义一个输入串流对象inS,从中输入一个整数和一个浮点数。再开辟一个字符串空间作为输出设备,定义一个输出串流对象outS,将从输入设备输入的两个变量的值输出。

  31. 9.4 控制符 • 9.4.1 使用流对象的成员函数 • 【例9-3】 使用width成员函数控制输出宽度。 • #include <iostream.h> • void main( ) • { • double values[ ]={1.44,36.47,625.7,4096.24}; • for(int i=0;i<4;i++) • {

  32. cout.width(10); • cout<<values[i]<<'\n'; • } • } • 程序运行结果为 • 1.44 • 36.47 • 625.7 • 4096.24

  33. 此例子在一列中以至少10个字符宽按右对齐方式输出数据。从程序的输出结果可以看到,在少于10个字符宽的数值前加入了引导空格。此例子在一列中以至少10个字符宽按右对齐方式输出数据。从程序的输出结果可以看到,在少于10个字符宽的数值前加入了引导空格。 • 空格是默认的填充符,当输出的数据不能充满指定的宽度时,系统会自动以空格填充。另外,还可以使用fill成员函数为已经指定宽度的域设置填充字符的值。为了用星号填充数值列,我们可以将例9-3中的for循环修改如下:

  34. for(int i=0;i<4;i++) • { • cout.width(10); • cout.fill('*'); • cout<<values[i]<<endl; • } • 其输出结果为 • ******1.44 • *****36.47 • *****625.7 • ***4096.24

  35. 9.4.2 使用控制符 • C++的输入/输出流类库提供了一些控制符,可以直接嵌入到输入/输出语句中来实现对I/O格式的控制。它的优点是程序可以直接将控制符插入流中,而不必单独调用。表9-4中列出了常用的I/O流类库控制符。

  36. 表9-4 常用的I/O流类库控制符

  37. 【例9-4】 使用setw控制符指定宽度。 • #include<iostream.h> • #include<iomanip.h> • void main( ) • { • double values[ ]={1.44,36.47,625.7,4096.24}; • char *names[ ]={"Rose","John","Alice","Mary"}; • for(int i=0;i<4;i++)

  38. cout<<setw(6)<<names[i]<<setw(10)<<values[i]<<endl; • } • width成员函数在头文件iostream.h中说明。 如果带参量使用setw(n)或任何其它控制符,还必须包括头文件iomanip.h。在输出中,字符串输出在宽度为6的域中,整数输出在宽度为10的域中。程序运行结果为 • Rose 1.44 • John 36.47 • Alice 625.7 • Mary 4096.24

  39. setw和width都不截断数值。如果一个数值需要比set(n)确定的字符数更多的字符,则该值将使用它所需要的所有字符。当然,还要遵守该流的精度设置。setw和width仅影响紧随其后的域,即使用setw和width设置的间隔方式并不保留其效力。在一个域输出完后,域宽度恢复成它的默认值 (必要的宽度),但其它流格式选项保持有效直到发生改变。

  40. 例如,下面的程序代码: • //... • cout <<setiosflags(ios::right) //设置为默认的右对齐方式, • <<setw(5)<<1 • <<setw(5)<<2 • <<setw(5)<<3<<endl; • cout <<setiosflags(ios::left) //设置成左对齐方式

  41. <<setw(5)<<1 • <<setw(5)<<2 • <<setw(5)<<3<<endl; • cout<<resetiosflags(ios::left) //关闭左对齐标志 • //... • 这段程序代码中,是通过使用带参数的setiosflags控制符来设置左、右对齐,参数是ios::left和ios::right枚举器。

  42. 该枚举器定义在ios类中,因此,引用时必须包括ios::前缀。这里需要用resctiosflags操纵符关闭左、右对齐标志。setiosflags不同于width和setw,它的影响是持久的,直到用resetiosflags重新恢复默认值时为止。该枚举器定义在ios类中,因此,引用时必须包括ios::前缀。这里需要用resctiosflags操纵符关闭左、右对齐标志。setiosflags不同于width和setw,它的影响是持久的,直到用resetiosflags重新恢复默认值时为止。 • 这段程序代码的输出结果为 • 1 2 3 • 1 2 3 • 常用控制符和流格式控制成员函数如表9-5所示。

  43. 表9-5 常用控制符和流成员函数

  44. 9.5 输入/输出成员函数 • 9.5.1 使用成员函数输入 • 1.getline( )函数 • 在程序使用cin输入时,cin用空白符和行结束符将各个值分开。有时候输入可能需要读取一整行文本并且分开不同的域,为此,我们可以使用getline成员函数。其函数原型如下: • istream&getline( char*pch, int nCount, char delim = '\n' );

  45. 其中,第一个参数是字符数组,用于放置读取的文本;第二个参数是本次读取的最大字符个数;第三个参数是分隔字符,作为读取一行结束的标志。其中,第一个参数是字符数组,用于放置读取的文本;第二个参数是本次读取的最大字符个数;第三个参数是分隔字符,作为读取一行结束的标志。 • getline成员函数的功能是允许从输入流中读取多个字符 (包括空白字符和行结束符),并且允许指定输入终止字符 (默认值是换行字符)。在读取完成后,从读取的内容中删除该终止字符。

  46. 【例9-5】 为输入流指定一个终止字符。 • 本程序连续读入一串字符,直到遇到字符t时停止,字符个数最多不超过99个。程序中的t是大小写敏感的。 • #include<iostream.h> • void main( ) • { • char line[100]; • cout<<"Type a line terminated by 't'"<<endl; • cin.getline(line,100,'t'); • cout<<line<<endl; • }

  47. 2.get( )函数 • 在输入时,有些时候需要执行每次只输入单个字符的操作,我们可以使用get( )成员函数来完成。get( )函数的格式如下: • char istream::get( ); • 【例9-6】 循环读入字符,直到键入一个y字符,或遇到文件尾。 • #include<iostream.h> • void main( ) • { • char letter; • while(!cin.eof( ))

  48. { • letter=cin.get( ); • if(letter=='y') • { • cout<<"'y'be met!"; • break; • } • cout<<letter; • } • }

More Related