第7章输入输出流_第1页
第7章输入输出流_第2页
第7章输入输出流_第3页
第7章输入输出流_第4页
第7章输入输出流_第5页
已阅读5页,还剩56页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

面向对象

——第7章输入输出流2主要内容流无格式输入/输出输入/输出的格式控制文件的输入/输出3分析问题C++没有定义任何用于执行输入或输出的语句,但可以使用C语言中的标准I/O函数printf()和scanf()来解决此问题。printf()与scanf()存在两个缺点:非类型安全不可扩充性

4C++使用类型安全的I/O流操作。不同类型的I/O流操作都是重载的,没有定义过I/O功能的类型不具备I/O操作的能力。C++标准库既可作为标准数据类型数据的I/O,也能用于自定义类型的对象的I/O,这种扩展性是C++最有价值的特点之一。C++用输入输出流来解决这个问题。5流所谓流(stream)是指数据从一个位置流向另一个位置。流是字节的序列。输入/输出是一种数据传递操作,可以看作字符序列在计算机内存与外设之间的流动,C++将数据从一个对象到另一个对象的流动抽象为“流”。流动的方向不同,构成输入/输出流,即I/O流。6I/O流在C++程序中,数据可以从键盘流入到程序,也可以从程序流向屏幕或磁盘文件。从流中获取数据的操作称为提取操作,向流中添加数据的操作称为插入操作。数据的输入/输出就是通过I/O流来实现的。7编译系统已经以运算符或函数的形式做好了对标准外设(键盘、屏幕、打印机、文件)的接口,使用时只需按照要求的格式调用即可。cin>>x;cout<<x;内存键盘文件光笔....输入流显示器文件打印机...输出流8I/O流类库的层次结构C++编译系统提供的I/O流类库含有两个平行基类:streambufiosios类有4个直接派生类:输入流类istream输出流类ostream文件流类fstreambase串流类strstreambase9I/O流类库的头文件iostream:I/O流类库的最主要的头文件,它包括操作所有I/O所需的基本信息,还包括cin、cout、cerr和clog共4个对象。iomanip:包含带参数的流操纵算子的有关信息。fstream:包含对文件I/O操作的有关信息。strstream:包含对内存格式化I/O操作的有关信息。stdiostream:包含混合使用C和C++风格的I/O操作的有关信息。10intmain(){floata,b,c,disc;cout<<“pleaseinputa,b,c:”;cin>>a>>b>>c;if(a==0)cerr<<“aisequaltozero,error!”<<endl;elseif((disc=b*b-4*a*c)<0)cerr<<“disc=b*b-4*a*c<0”<<endl;else{cout<<“x1=”<<(-b+sqrt(disc))/(2*a)<<endl;cout<<“x2=”<<(-b-sqrt(disc))/(2*a)<<endl;}return0;}1:pleaseinputa,b,c:023aisequaltozero,error!2:pleaseinputa,b,c:523disc=b*b-4*a*c<03:pleaseinputa,b,c:12.51.5x1=-1x2=-1.511无格式输入/输出无格式输入/输出就是按系统预定义的格式进行的输入/输出。按默认约定,每个C++程序都能使用标准I/O流,如标准输入、标准输出。cin用来处理标准输入,即键盘输入;cout用来处理标准输出,即屏幕输出。它们被定义在iostream头文件中。在使用cout和cin前,要用编译预处理命令将所使用的头文件包含到源程序中,其格式如下:#include<iostream>12无格式输出“<<”是预定义的插入运算符,作用在流类对象cout上,实现默认格式的屏幕输出。使用cout输出表达式值到屏幕上的格式如下:

cout<<E1<<E2<<…<<Em;

其中,E1、E2、…、Em为均为表达式。用“cout<<”输出基本类型的数据时,可以不必考虑数据是什么类型,系统会判断数据的类型,并调用与之匹配的运算符重载函数。13无格式输出cout是ostream流类的对象,它在iostream头文件中作为全局对象定义,其格式如下:

ostreamcout(stdout);

其中,stdout表示标准输出设备名(屏幕)。14无格式输入“>>”是预定义的提取运算符,作用在流类对象cin上,实现默认格式的键盘输入。使用cin将数据输入到变量的格式如下:

cin>>V1>>V2>>…>>Vn;

其中,V1、V2、…、Vn都是变量。功能是暂停执行程序,等待用户从键盘输入数据,各数据间用空格或Tab键分隔,输入数据类型要与接受变量类型一致,输完后,按回车键结束。15无格式输入cin是istream流类的对象,它在iostream头文件中作为全局对象定义,其格式如下:

istreamcin(stdin);

标准输入设备名(键盘)16输入输出的格式控制C++提供了两种格式化输入/输出方式:一种是用流对象的有关成员函数进行格式化输入输出另一种是用专门的控制符进行格式化输入输出17

用流对象的成员函数格式化流成员函数主要是通过对状态标志、输出宽度、填充字符以及输出精度的操作来完成输入/输出格式化。输入/输出的格式由各种状态标志来确定,在ios类中定义为枚举量。枚举量定义在ios类中,因此引用时必须包含ios::前缀。使用时应该全部用符号名,绝不要用数值。18用流对象的成员函数对状态标志进行操作

ios类有3个成员函数可以对状态标志进行操作,并且定义了一个long型数据成员记录当前状态标志。这些状态标志可用位或运算符“|”进行组合。用setf函数设置状态标志,其一般格式如下:

longios::setf(longflags)19用流对象的成员函数对状态标志进行操作清除状态标志用unsetf函数清除状态标志,其一般格式如下:

longios::unsetf(longflags)20用流对象的成员函数对状态标志进行操作用函数flags取状态标志有两种形式,其格式分别如下:

longios::flags()//返回与流相关的当前状态标志值

longios::flags(longflag)//将流的状态标志值设置为flag,并返回设置前的状态标志值。21用流对象的成员函数对状态标志进行操作以上三组函数必须用流类对象(cin或cout)来调用,其格式如下:

<流对象名>.<函数名>(ios::<状态标志>)

cout.setf(ios::showpos);cout.setf(ios::scientific);cout.setf(ios::showpos|ios::scientific);2200000010000000010011001000100001001000100010000100100010001000010000100000000000voidshowflags(longf);intmain(){longf;f=cout.flags();//取当前状态标志

showflags(f);//显示状态值

cout.setf(ios::showpos|ios::scientific|ios::fixed);//追加状态标志

f=cout.flags();//取当前状态标志

showflags(f);//显示状态值

cout.unsetf(ios::scientific);//从状态标志中去掉scientificf=cout.flags();//取当前状态标志

showflags(f);//显示状态值

f=cout.flags(ios::hex);//重新设置状态标志

showflags(f);f=cout.flags();//取当前状态标志

showflags(f);return0;}voidshowflags(longf){longi;for(i=0x8000;i;i=i>>1)//用右移方式使i中的值为"1"的位不断右移

if(i&f)cout<<"1";//判断f中的某一位是否为"1"elsecout<<"0";cout<<endl;}【例】示例对状态标志的操作。23用流对象的成员函数设置输出宽度设置输出宽度函数有两种形式,其格式分别如下:

intios::width(intlen) intios::width()第一种形式是设置输出宽度,并返回原来的输出宽度;第二种形式是返回当前输出宽度,默认输出宽度为0。只对其后的第一个输出项有效。24设置填充字符填充字符的作用是当输出值不满输出宽度时用填充字符来填充,默认填充字符为空格。它与width()函数配合使用,否则没有意义。设置填充字符函数有两种形式,其格式分别如下:

charios::fill(charch)charios::fill()第一种形式是重新设置填充字符,并返回设置前的填充字符;第二种形式是返回当前的填充字符。25设置输出精度设置浮点数输出精度有两种形式,其格式分别如下:

intios::precision(intp)intios::precision()第一种形式是重新设置输出精度,并返回设置前的输出精度;第二种形式是返回当前的输出精度。默认输出精度为6。26以上三组函数必须用流类对象(cin或cout)来调用。27width:08(newwidth)fillingwordis:(ASCIIcode32)*(42)(newfillingword)precision:6123.45679(example)8(newprecision)intmain(){inti;i=cout.width();cout<<"width:"<<i<<endl;cout.width(8);cout<<cout.width()<<"(newwidth)"<<endl;charc;c=cout.fill();cout<<"fillingwordis:"<<c<<"(ASCIIcode"<<(int)c<<")"<<endl;cout.fill('*');cout<<cout.fill()<<"("<<(int)cout.fill()<<")(newfillingword)"<<endl;intj;j=cout.precision();cout<<"precision:"<<j<<endl;cout.precision(8);cout<<123.456789<<"(example)"<<endl;cout<<cout.precision()<<"(newprecision)"<<endl;return0;}【例】示例设置输出宽度、填充字符、输出精度。28用控制符格式化为了不直接以标志位的方式去处理流的状态,c++标准库提供了标准的控制符专门操控这些状态。这组控制符不属于任何类成员,定义在iomanip头文件中。将它们用在提取运算符“>>”或插入运算符“<<”后面来设定输入/输出格式,即在读写对象之间插入一个修改状态的操作。

29设置输入/输出宽度setw(int)用整型参数来制定输入/输出域的宽度。使用时只对其后一项输入/输出有效。当用于输出时,若实际宽度小于设置宽度时,数据向右对齐,反之则按数据的实际宽度输出。当用于输入时,若输入的数据宽度超过设置宽度时,超出的数据部分被截断而被作为下一项输入内容。3012345678123456781234512345i:10#include<iostream>#include<iomanip>usingnamespacestd;intmain(){char*p="12345",*q="678";charf[4],g[4];//最后一位为'\0'inti=10;cout<<p<<setw(6)<<q<<setw(4)<<p<<q<<endl;//设置输出宽度

cin>>setw(4)>>f>>g;//设置输入宽度

cout<<f<<endl<<g<<endl<<"i:"<<i<<endl;return0;}【例】用控制符示例设置输入/输出宽度31设置输出填充字符setfill(char)与ios::fill相同,常与setw(int)联合使用,从而向不满设置输出宽度的空间填入指定的字符,不设置则填空格。设置后直至下一次设置前一直有效。参数可以是字符常量或字符变量。设置输出精度setprecision(int)指明输出实数的有效位数。参数为0时,按默认有效位数6输出。在以fixed形式和scientific形式输出时参数为小数位数。32setiosflags(ios::fixed)用定点方式表示实数。setiosflags(ios::scientific)用科学记数法方式表示实数。如果setprecision(n)与setiosflags(ios::fixed)合用,可以控制小数点右边的数字个数。如果setprecision(n)与setiosflags(ios::scientific)合用,可以控制科学记数法中尾数的小数位数。

setiosflags(ios::left)输出数据左对齐setiosflags(ios::right)输出数据右对齐33setiosflags(ios::uppercase)大写表示setiosflags(ios::showpos)输出正数时给出“+”号setiosflags(ios::skipws)忽略前导空格resetiosflags()终止已设置的输出格式状态,在括号中应指定内容34Zoot1.23Jimmy35.36Al653.7Stan4358.24#include<iostream>#include<iomanip>usingnamespacestd;intmain(){doublevalues[]={1.23,35.36,653.7,4358.24};char*names[]={"Zoot","Jimmy","Al","Stan"};for(inti=0;i<4;i++)cout<<setiosflags(ios::left)//设置左对齐

<<setw(6)<<names[i]<<resetiosflags(ios::left)//取消左对齐

<<setw(10)<<values[i]<<endl;return0;}【例】设置对齐方式和输出宽度示例353.142863.143.14285714#include<iostream>#include<iomanip>usingnamespacestd;intmain(){doublef=22.0/7;//在用浮点形式表示的输出中,setprecision(n)表示实数的有效位数

cout<<f<<endl;//默认有效位数为6cout<<setprecision(3)<<f<<endl;//设置有效位数为3//在用定点形式表示的输出中,setprecision(n)表示实数的小数位数

cout<<setiosflags(ios::fixed);cout<<setprecision(8)<<f<<endl;//小数位数为8return0;}【例】分别用浮点、定点的方式表示一个实数cout<<setprecision(8);cout<<setiosflags(ios::scientific)<<f<<endl;//尾数小数位数为83.14285714e+00036设置输入/输出整型数数制dec、hex和oct。控制换行的控制符endl

代表输出单字符“\0”的控制符ends37用户自定义控制符函数建立输出控制符函数的格式如下:

ostream&manip_name(ostream&stream){<自定义语句序列>returnstream;}控制符函数名38#include<iostream>#include<iomanip>usingnamespacestd;ostream&setup(ostream&stream){stream.setf(ios::left);stream<<setw(10)<<setfill('$');returnstream;}intmain(){cout<<10<<""<<setup<<10<<endl;return0;}【例】示例用户自定义输出控制符函数1010$$$$$$$$39用户自定义控制符函数建立输入控制符函数的格式如下:

istream&manip_name(istream&stream){<自定义语句序列>returnstream;}操作符函数名40#include<iostream>#include<iomanip>usingnamespacestd;istream&prompt(istream&stream){cin>>hex;cout<<"Enternumberusinghexformat:";returnstream;}intmain(){inti;cin>>prompt>>i;cout<<i<<endl;return0;}【例】示例用户自定义输入控制符函数Enternumberusinghexformat:ff25541

文件的输入/输出C++把文件看作是一个字符(字节)的序列,即由一个个字符(字节)顺序组成。根据数据的组织形式,可分为ASCII码文件和二进制文件。ASCII码文件又称为文本文件,它的每一个字节存放一个ASCII码,代表一个字符。二进制文件是把内存中的数据按其在内存中的存储形式原样输出到磁盘文件存放。42由于ASCII码形式与字符一一对应,因此便于对字符进行输出或逐个处理,但它要占用较多的存储空间,若存于二进制文件中,可以节省存储空间,但不能直接输出字符形式。

56:ASCII表示为0011010100110110,占两字节

56:二进制表示为111000,占六个二进制位43C++在头文件fstream中定义了C++的文件流类体系,当程序中使用文件时,要包含头文件fstream,其中定义了各种文件操作运算符及函数。iosifstream(输入文件流)ofstream(输出文件流)fstream文件流定义用于输入的文件对象定义用于输出的文件对象定义用于输入输出的文件对象44内存变量(程序)键盘输入文件屏幕输出文件cin>>xcout<<xinfile>>xoutfile<<x程序对文本文件的操作与对键盘、显示器的操作比较:在涉及文本文件的操作时,将输入文件看成键盘,将输出文件看成显示器,格式不变。只需在程序中增加打开与关闭文件的语句。45C++中进行文件操作的一般步骤

为文件定义一个流类对象;使用open()函数建立(或打开)文件。如果文件不存在,则建立该文件;如果磁盘上已存在该文件,则打开该文件;进行读写操作。在建立(或打开)的文件上执行所要求的输入/输出操作。一般来说,在内存与外设的数据传输中,由内存到外设称为输出或写,反之则称为输入或读;使用close()函数关闭文件。当完成操作后,应把打开的文件关闭,避免误操作。46在C++中,打开一个文件就是将这个文件与一个流建立关联;关闭一个文件就是取消这种关联。open()函数的原型在fstream中定义。其原型为:

voidopen(char*filename,intmod,intaccess);其中第一个参数是用来传递文件名;第二个参数的值决定文件的使用方式;第三个参数的值决定文件的访问方式。对于ifstream流类,mod的值为ios::in;对于ofstream流类,mod的值为ios::out47打开文件先建立流对象,然后调用函数open连接外部文件

流类对象名;

对象名.open(文件名,方式);调用流类带参数的构造函数,建立流对象的同时连接外部文件

流类对象名(文件名,方式);

其中,“流类”为ifstream、ofstream或fstream。文件的打开与关闭48关闭文件使用close()成员函数进行关闭:流对象名.close()

其中,流对象名是待关闭的文件流的对象名。文件的打开与关闭49120,310.85#include<iostream>#include<fstream>usingnamespacestd;intmain(){ ofstreamostrm;

//定义流类对象

ostrm.open("f1.dat");//打开文件

ostrm<<120<<endl;//写操作

ostrm<<310.85<<endl; ostrm.close();//关闭文件

ifstreamistrm("f1.dat");//定义流类对象

intn; doubled; istrm>>n>>d;//读操作

cout<<n<<","<<d<<endl; istrm.close();//关闭文件

return0;}【例】示例文件的输入/输出操作。50文本文件的读写:文本文件用默认方式打开。文件的读写#include<iostream>#include<fstream>usingnamespacestd;intmain(){chars1[80],s2[8];fstreamoutfile;cin>>s1;outfile.open("exam.txt",ios::out);if(!outfile){cout<<"exam.txtcan’topen"<<endl;abort();}outfile<<s1;outfile.close();

outfile.open("exam.txt",ios::in);outfile>>s2;cout<<s2<<endl;outfile.close();return0;}51二进制文件的读写若在文件的打开方式中没有特别说明,打开的文件均为ASCII码文件,若要打开二进制文件,则要特别说明并用特定的读写函数。二进制文件用binary方式打开,读写方式完全由程序控制。fstreaminfile,outfile;infile.open(“inf1.dat”,ios::in|ios::binary);outfile.open(“outf1.dat”,ios::out|ios::binary);

文件名

输入方式打开

二进制文件

文件名

输出方式打开

二进制文件文件的读写52输入函数:infile.read(char*,int)输入文件对象名

数据进入的内存地址

一次读入的字节数inta[10];infile.read((char*)a,10*sizeof(int));//从文件中输入十个整型数到ainti;infile.read((char*)&i,sizeof(int));//从文件中输入一个整型数到i由于二进制文件中的数据不是ASCII码,故不能直接对其读写,必须要通过特定的函数予以转换。文件内存读入地址要强制转换成字符型53输出文件对象名

要输出的数据在内存中的地址

一次输出的字节数inta[10]={0,1,2,3,4,5,6,7,8,9};outfile.write((char*)a,10*sizeof(int));//向文件输出一个整型数组ainti=4;outfile.write((char*)&i,sizeof(int));//向文件输出一个整型数i输出函数:outfile.write(char*,int)文件内存写出地址要强制转换成字符型54【例】二进制文件的读写structperson{charname[20];doubleheight;unsignedshortage;}people[3]={"wang",1.65,25,"zhang",1.78,24,"li",1.85,21};intmain(){fstreaminfile,outfile; outfile.open("exam.dat",ios::out|ios::binary);if(!outfile){cout<<"exam.datcan'topen"<<endl;abort();}for(inti=0;i<3;i++) outfile.write((char*)&people[i],sizeof(people[i]));

outfile.close(); infile.open("exam.dat",ios::in|ios::binary);if(!infile){cout<<"exam.datcan'topen"<<endl;abort();}for(intj=0;j<3;j++){infile.read((char*)&people[j],sizeof(people[j])); cout<<people[j].name<<"\t"<<people[j].height<<"\t"<<people[j].age<<endl;} infile.close(); return0;}55文件的随机读写:文件打开以后,系统自动生成两个隐含的流指针:读指针和写指针。在输入文件流类中,有关读指针的函数如下:移动读指针函数istream&istream::seekg(streampospos);

该函数的功能是将输入文件的指针移动到pos指定的位置中。文件的读写56istream&istream::seekg(streamoffoffset,seek_dirorigin);其中,origin的类型seek_dir是一个枚举类型,有以下三种取值:ios::beg表示指针的起始位置为文件头ios::cur表示指针的起始位置为当前位置ios::end表示指针的起始位置为文件尾该函数的功能是从origin指定的开始位置起,将文件指针移动offset个字节数。文件的读写57返回读指针当前指向的位置值 streamposistream::tellg();该函数的功能是确定文件指针的当前位置。文件的读写58相应地,ostream类提供有关写指针的函数如下:移动写指针函数ostream&ostream::seekp(streampospos);ostream&ostream::seekp(streamoffoffset,seek_dirorigin);返回写指针当前指向的位置值streamposostream::tellp();

函数参数的意义与读指针函数一样。文件的读写59【例】文件的随机读写intmain(){fstreamfile("exam.dat",ios::in|ios::out|ios::binary);if(!file){cout<<"exam.datcan’topen"<<endl;abort();}for(inti=0;i<15;i++)file.write((char*)&i,sizeof(int));streampospos=file.tellp();cout<<"currentbytenumber:"<<pos<<endl;for(i=15;i<45;i++)file.write((char*)&i,sizeof(int));file.seekg(pos);file.read((char*)&i,sizeof(int));cout<<"Thedatastoredis"<<i<<endl;file.seekp(0,ios::beg);for(i=80;i<10

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论