1、,第七章 I/O流及输入输出,本章要求,理解流的概念 掌握C+的控制台I/O 掌握C+的文件I/O,输入/输出,在C+中,输入/输出操作是一种基于字节流的操作。流:字节序列的抽象概念。 流提供了一种用统一的方法从各种I/O设备中读取和向其中写入字节序列的方法。 文件是数据的静态存储形式。 流是指数据传输时的形态。,流,流,流,在程序中,“流”具体体现为一个对象,负责在数据生产者和数据消费者之间建立联系,控制数据的流动。例如cin、cout就是两个流对象,由于C+支持过程式和面向对象两种程序设计范型,因此,在C+中,输入/输出操作也可以以这两种方式来进行,C+标准库也以两种方式提供了输入/输出功
2、能。 在C+中,以过程式的方式进行输入/输出是通过从C语言保留下来的函数库中的输入/输出函数来实现的,用这些函数可以实现对基本类型数据的I/O操作。 以面向对象方式进行输入/输出则是通过C+的I/O类库来实现的。I/O类库提供的输入/输出操作是由一些I/O类来实现的。,C+的输入/输出,C+的流类库-类模板,C+的流类库,流类库的头文件,: 包括istream、ostream、iostream以及cin、cout、ceer和clog对象的定义,同时提供非格式化和格式化的I/O服务。针对标准设备的I/O操作,须包含之。 : 包括istringstream、ostringstream、string
3、stream的定义,要使用字符串流对象进行针对内存字符串空间的I/O操作,须包含此文件。,10,流类库的头文件,: 包括ifstream、ofstream、fstream的定义,要使用文件流对象进行针对磁盘文件的I/O操作,须包含此文件。 : 包括setw、fixed等等操纵符的定义,利用操纵符进行格式化I/O操作,须包含之。,11,istream类提供了(提取),用它可以进行基本类型数据的输入操作。ostream类提供了,进行重载,使得通过I/O类的对象可以对用户自定义的数据(如对象等)进行输入/输出操作。,C+的流类库,第七章 I/O流及输入输出,控制台I/O 文件I/O,第七章 I/O流
4、及输入输出,控制台I/O 文件I/O,7.1 控制台I/O,控制台I/O指从计算机系统的标准输入设备输入程序所需要的数据以及把程序的计算结果输出到计算机系统的标准输出设备。,预定义的控制台对象,在I/O类库中预定义了四个I/O对象:cin,cout,cerr,clog,利用这些对象可以直接进行控制台的输入/输出。 cin属于istream类的对象,它对应计算机的标准输入设备,用来处理标准输入,即键盘输入。 cout,cerr以及clog属于ostream类的对象,cout对应计算机的用于输出程序正常运行结果的标准输出设备,而cerr和clog则对应计算机的用于输出程序错误信息的设备,用来处理标
5、准出错信息,通常它们都对应显示器。cerr不对输出信息进行缓冲。,内存缓冲区,有效地提高了CPU的使用率 有机会回滚部分写入的数据,应用程序,内存缓冲区,I/O设备,屏幕输出,使用预定义的插入符,使用成员函数,ostream& ostream:put(char ch):输出一个字符,ostream& ostream:write(const char *p,int count):输出p所指向内存空间中count个字节。,cout.put(m); char c=a;cout.put(c);,cout.write(“hello”,strlen(“hello”);,例:向标准设备输出字符串,#incl
6、ude using namespace std; int main() char *word = “hello world!“;double pi = 3.1415926;int dayOfYear = 365;cout“value of word is:“wordendl;cout“PI = “piendl;cout“days of year: “dayOfYearendl;cout.put(B).put(C).put(n); return 0; ,19,运行结果: value of word is: hello world! PI = 3.14159 days of year: 365 B
7、C,例(续),屏幕输出,为了对输出格式进行进一步的控制,可以通过输出一些操纵符(manipulator)来实现。(书p281),键盘输入,使用预定义的提取符,在输入时,各个数据之间用空白符分开,一般常用空格符、也可用tab键(水平制表符)或换行符。因此,从键盘输入字符时,空白符只用于输入字符的分隔符,而本身不作为从输入流中提取的字符。,提取符可以从输入流中读取一个字符序列,即一个字符串。在处理这种字符序列时,字符串被认为是一个以空白符结束的字符序列。在从输入流中,每读入一个字符串,系统自动加上0字符。,使用成员函数,istream:get(char &ch):输入一个字符,该函数不忽略空白字符
8、,即将输入流的空白字符也作为一个字符。 get()函数从指定流输入一个字符并将这个值作为函数调用的返回值返回,在遇到文件尾时返回EOF。 在Windows系统中,EOF=+z,键盘输入,例:输入字符串,#include using namespace std; int main() int character;cout“before input, cin.eof()“cin.eof()endl;cout“please input a sentence:“endl;while(character = cin.get() != EOF)cout.put(character);cout“EOF in
9、 this system is:“characterendl;cout“after input of EOF, cin.eof() = “cin.eof()endl;return 0; ,24,运行结果: before input, cin.eof() = 0 please input a sectence: I am a good C+ programmer I am a good C+ programmer Z EOF in this system is: -1 After input of EOF, cin.eof() = 1,例(续),25,I/O流的状态,C+ I/O流的状态用ios
10、_base中一组状态标志位来表示,同时定义了一组判断、操纵这些标志位的成员函数,常用的有 bool good()const:刚进行的操作成功时返回true,否则返回false; bool fail()const:与good()相反,刚进行的操作失败时返回true,否则返回false;,26,I/O流的状态,C+ I/O流的状态用ios_base中一组状态标志位来表示,同时定义了一组判断、操纵这些标志位的成员函数,常用的有 bool bad()const:如果进行了非法操作返回true,否则返回false;bad()为true时fail()必为true; bool eof()const:进行输入
11、操作时,若到达流尾返回true,否则返回false,通常只用于输入流;eof()为true时fail()必为true; void clear():将流置为正常状态,使得good()返回true。,27,使用成员函数,istream:get(char &ch):输入一个字符,该函数不忽略空白字符,即将输入流的空白字符也作为一个字符。,istream:getline(char *p,int count,char delim=n):输入一个字符串直到输入count-1个字符或遇到delim指定的字符为止,并自动加上一个0.,istream:read(char *p,int count):读入coun
12、t个字符至p所指向的内存空间。,键盘输入,键盘输入,从输入流提取时,可以使用操纵符。常用的操纵符有dec,oct和hex,skipws(忽略空白,默认), noskipws (不忽略空白),30,31,32,例:输入/输出的数制控制示例,#include #include using namespace std;int main() int i,j;cinhexij;coutitj;coutendloctitshowbasejendl;return 0; ,33,运行结果: 0x3f FA 63 250 77 0372,例(续),34,格式控制操纵符(续),输入/输出宽度的控制 有关的操纵符是
13、: setw(n) 功能:设置输入/输出宽度,其中n为表示宽度的整数;,35,格式控制操纵符(续),输出精度的控制 精度是针对浮点数设置的,精度设置对于输入流无效。对于输出流,初始精度值为6,可以通过设置改为任意精度;将精度设置0意味着回到初始精度6。有关操纵符是: setprecision(n) 功能:设置浮点数的精度,其中n为精度的整数;,36,的重载,为了能用和。,class A int x,y;public:friend ostream& operator (ostream & out,const A &a) ,ostream ,A a,b; coutabendl;,的重载,第七章 I
14、/O流及输入输出,控制台I/O 文件I/O,7.2文件I/O,程序运行结果有时需要永久保存起来,以供其它程序或本程序下一次运行时使用。程序运行所需要的数据也常常要从其他程序或本程序上一次运行所保存的数据中获得。用于永久性保存数据的设备称为外部存储器,如磁盘、光盘等。 在外部存储器中保存数据的方式通常有两种:文件和数据库。,文件I/O,文件是在计算机内存中以二进制表示的数据在外部存储介质上的另一种存放形式。在C+中,把文件看成是由一系列字节所构成的字节串,称为流式文件。对文件中数据的操作(输入、输出)通常是逐个字节顺序进行。,文件,文本文件和二进制文件,文件就是一片内存中的数据在硬盘上的另一种存
15、放形式,也就是二进制数据,即每个文件都是二进制的。 如果一个文件中的每个字节的内容都可以表示成字符的数据,我们就称这个文件为文本文件。 除了文本文件之外的文件称为二进制文件。,在对文件数据进行读写前,首先要打开文件。每个文件流都应当与一个打开的文件相联系。可以用两种不同的方式打开文件。1)在建立文件流对象的同时打开文件 如:ifstream fin(“datafile.dat“); 2)先建立文件流对象,再在适当的时候打开文件, 如:ifstream fin;fin.open(“datafile.dat“);,文件打开,fstream iofile(文件名,打开方式);,ofstream ou
16、tfile; outfile.open(文件名,打开方式);,fstream iofile; iofile.open(文件名,打开方式);,ifstream infile; infile.open(文件名,打开方式);,ofstream outfile(文件名,打开方式);,ifstream infile(文件名,打开方式);,文件打开,可以通过构造函数或open函数的第二个参数,指定文件的打开模式。打开模式被定义为一组枚举常量:,46,当我们按照文本方式往文件中写入数据时,一旦遇到换行字符(ASCII为10),则会转换为回车换行(ASCII为13、10)。在读取文件时,一旦遇到回车换行的组合
17、(即连续的ASCII 13、10),则会转换为换行字符(ASCII为10)。 当我们按照二进制方式往文件中写入数据,则将数据在内存中的存储形式原样输出到文件中。,文本方式和二进制方式,每个被打开的文件都有一个内部的位置指针,他指出文件的当前读写位置。,进行读/写操作时,每读/写一个字节,文件指针就会自动往后移动一个字节的位置。,文件打开,由于种种原因,打开文件操作可能失败。因此,打开文件时应判断打开是否成功,只有文件打开成功后才能对文件进行操作。判断文件打开是否成功可采用以下方式:if(!outfile) 或(outfile.fail()或!outfile.is_open(),文件打开,文件打
18、开成功后可以使用插入符和成员函数get,geline,read来进行文件读操作。,文件读写,两种特殊的文件流,以文件名“CON“打开的输入文件流所联系的设备是键盘,可用于键盘输入;以“CON“为文件名打开的输出文件流所联系的设备是显示器,以“CON“为文件名打开的输入/输出文件流所联系的设备是终端,即键盘加显示器。 用文件名“PRN“打开的输出文件流所联系的设备是打印机, 例如:ofstream Printer(“PRN“); Print“此行文字被打印出来“endl;,51,为了能够随机读写文件中的数据,必须要显示地指出读写的位置。 对于以输入方式打开的文件,可用下面的操作来指定文件内部指针
19、位置。seekg(位置);/指定绝对位置seekg(偏移量,参照位置); /指定绝对位置tellg()/获取指针位置。,文件随机访问,其中位置和偏移量都是long型量,并以字节数为单位。 参照位置可以是ios:beg(文件头)、ios:cur(当前位置) 、ios:end(文件尾),文件随机访问,对于以输出方式打开的文件,可用下面的操作来指定文件内部指针位置。seekp(位置);/指定绝对位置 seekp(偏移量,参照位置); /指定绝对位置 tellp()/获取指针位置。,文件随机访问,关闭文件用成员函数close( ).文件读写完毕后,通常要关闭文件,其目的是把暂存在内存缓冲区中的内容写入
20、到文件中,并归还打开文件时申请的内存资源。 如果程序没有用close()主动关闭文件,则在文件流对象退出其作用域时,将自动调用文件流对象的析构函数关闭所联系的文件。缓冲区中尚未写入文件的数据将在文件关闭时实际地写入到文件中。当不再使用文件时立即关闭文件是一个好的习惯,这除了能够尽早释放流对象所占用的计算机资源之外,还有利于文件中数据的安全。,文件关闭,例: CopyFile接收两个参数:输入文件名和输出文件名,完成从输入文件和输出文件的拷贝,56,例(续),/CopyFile.h #include #include using namespace std; void CopyFile(cons
21、t char *from, const char *to);,/CopyFile.cpp #include“CopyFile.h“ void CopyFile(const char *from, const char *to) cin.clear();ifstream inf(from);if(!inf)cerr“输入文件打开失败!“endl;exit(1);,if(!outf)cerr“输出文件打开失败!“endl;exit(3);while(!inf.eof() outf.put(inf.get();inf.close();outf.close(); ,/11-12.cpp #include“CopyFile.h“int main()char fin30,fout30;coutfin;coutfout;CopyFile(fin,fout);return 0; ,60,