面向对象程序设计07-1输入输出流对象课件_第1页
面向对象程序设计07-1输入输出流对象课件_第2页
面向对象程序设计07-1输入输出流对象课件_第3页
面向对象程序设计07-1输入输出流对象课件_第4页
面向对象程序设计07-1输入输出流对象课件_第5页
已阅读5页,还剩143页未读 继续免费阅读

下载本文档

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

文档简介

《面向对象程序设计》七、输入/输出流对象1/4/20231第7章输入/输出流对象《面向对象程序设计》七、输入/输出流对象12/30/2022内容提要螺旋矩阵的输入/输出问题流无格式输入/输出输入/输出的格式控制自定义类型对象的输入输出文件的输入/输出问题1/4/20232第7章输入/输出流对象内容提要螺旋矩阵的输入/输出问题12/30/20222提出问题编程输出M*M的螺旋矩阵,要求数据间距与M相同。例如,4*4的螺旋矩阵,其间距为4:

123412131451116156109871/4/20233第7章输入/输出流对象提出问题编程输出M*M的螺旋矩阵,要求数据间距与M相同。例如分析问题C++没有定义任何用于执行输入或输出的语句,但可以使用C语言中的标准I/O函数printf()和scanf()来解决此问题。1/4/20234第7章输入/输出流对象分析问题C++没有定义任何用于执行输入或输出的语句,但可以使【例】有如下程序:#include<stdio.h>intb=20;floata=5.6;intmain(){printf("%d\n",a);scanf("%d",&a);scanf("%d",&b);printf("%d\n","abc");return0;}该程序的运行结果为:161061273623↙45↙43499801/4/20235第7章输入/输出流对象【例】有如下程序:该程序的运行结果为:12/30/20225printf()与scanf()存在以下两个缺点:1.非类型安全2.不可扩充性classA{…}Aa;…printf("%?",a);//不知用什么格式符来识别A的对象1/4/20236第7章输入/输出流对象printf()与scanf()存在以下两个缺点:12/30C++用I/O流来解决这个问题。下面先介绍流的概念。1/4/20237第7章输入/输出流对象C++用I/O流来解决这个问题。12/30/20227第7章流的概念在C++程序中,数据可以从外部设备(键盘等)流入到计算机内存中,也可以从计算机内存流向外部设备(屏幕或磁盘文件等),这种数据传递被称作输入输出。C++将数据从一个位置到另一个位置的传递抽象为流。所谓流(stream)就是指数据从一个位置流向另一个位置。流是字节的序列。C++的输入输出操作是基于流来处理的。1/4/20238第7章输入/输出流对象流的概念在C++程序中,数据可以从外部设备(键盘等)流入到I/O流操作C++基于流的概念处理数据的输入输出,因此也称之为输入输出流,即I/O流。I/O流具有两个基本的行为特征,一是从流中获取数据的操作称为提取操作,二是向流中添加数据的操作称为插入操作。1/4/20239第7章输入/输出流对象I/O流操作C++基于流的概念处理数据的输入输出,因此也称之I/O流类C++标准库围绕流的概念,提供了一整套I/O流类簇,既可用于标准类型数据的I/O,也能用于自定义类型对象的I/O,这种扩展性是C++最有价值的特点之一。C++标准库提供的I/O流类的各种操作都是类型安全(typesafe)的。不同类型的I/O流操作都是重载的,没有定义过I/O功能的类型不具备I/O操作的能力。1/4/202310第7章输入/输出流对象I/O流类C++标准库围绕流的概念,提供了一整套I/O流类簇I/O流类簇的层次结构C++标准库提供的I/O流类簇有两个平行基类:streambuf(filebuf,stringbuf,strstreambuf)ios(istream,ostream)ios类有下面直接派生类:输入流类istream (ifstream,istringstream,istrstream)输出流类ostream (ofstream,ostringstream,ostrstream)(iostream->fstream,stringstream,strstream)1/4/202311第7章输入/输出流对象I/O流类簇的层次结构C++标准库提供的I/O流类簇有两个I/O流分类C++标准库提供的I/O流按功能可分为如下3类:标准I/O流:内存与标准输入输出设备(键盘、屏幕)之间数据的传递;文件I/O流:内存与外部磁盘文件之间数据的传递;字符串I/O流:内存变量与表示字符串流的字符数组之间数据的传递。1/4/202312第7章输入/输出流对象I/O流分类C++标准库提供的I/O流按功能可分为如下3类:标准I/O流对象标准I/O流预定义了4个流类对象:cin、cout、cerr、clog。操作系统给把外设用文件名的方式进行管理,因此程序设计要访问外设就跟访问文件一样方便。

1/4/202313第7章输入/输出流对象标准I/O流对象标准I/O流预定义了4个流类对象:cin、cI/O分为无格式支持的低级I/O和具有格式支持的高级I/O。无格式支持的低级I/O以基本字节为操作对象,有格式支持的高级I/O把若干字节组合成有意义的单位,如整数、浮点数、字符、字符串及用户自定义类型等等。1/4/202314第7章输入/输出流对象I/O分为无格式支持的低级I/O和具有格式支持的高级I/O。无格式输入/输出无格式输入/输出就是按系统预定义的格式进行的输入/输出。按默认约定,每个C++程序都能使用标准I/O流,如标准输入、标准输出。cin用来处理标准输入,即键盘输入;cout用来处理标准输出,即屏幕输出。它们被定义在iostream头文件中。在使用cout和cin前,要用编译预处理命令将所使用的头文件包含到源程序中,其格式如下:

#include<iostream>1/4/202315第7章输入/输出流对象无格式输入/输出无格式输入/输出就是按系统预定义的格式进行无格式输出“<<”是预定义的插入运算符,作用在流类对象cout上,实现默认格式的屏幕输出。使用cout输出表达式值到屏幕上的格式如下:

cout<<E1<<E2<<…<<Em; 其中,E1、E2、…、Em为均为表达式。功能是计算各表达式的值,并将结果输出到屏幕当前光标位置处。1/4/202316第7章输入/输出流对象无格式输出“<<”是预定义的插入运算符,作用在流类对象co无格式输出cout是ostream流类的对象,它在iostream头文件中作为全局对象定义,其格式如下: ostreamcout(stdout); 其中,stdout表示标准输出设备名(屏幕)。在ostream流类中,对应每个基本数据类型定义运算符“<<”重载函数为友元,它们在ostream中声明:ostream&operator<<(ostream&dest,char*pSource);ostream&operator<<(ostream&dest,intsource);ostream&operator<<(ostream&dest,charsource);1/4/202317第7章输入/输出流对象无格式输出cout是ostream流类的对象,它在iost无格式输入“>>”是预定义的提取运算符,作用在流类对象cin上,实现默认格式的键盘输入。使用cin将数据输入到变量的格式如下:

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

其中,V1、V2、…、Vn都是变量。功能是暂停执行程序,等待用户从键盘输入数据,各数据间用空格或Tab键分隔,输入数据类型要与接受变量类型一致,输完后,按回车键结束。1/4/202318第7章输入/输出流对象无格式输入“>>”是预定义的提取运算符,作用在流类对象ci无格式输入cin是istream流类的对象,它在iostream头文件中作为全局对象定义,其格式如下: istreamcin(stdin);在istream流类中,对应每个基本数据类型定义运算符“>>”重载函数为友元,它们在istream中声明: istream&operator>>(istream&sour,char*pDes); istream&operator>>(istream&sour,intdes); istream&operator>>(istream&sour,chardes);1/4/202319第7章输入/输出流对象无格式输入cin是istream流类的对象,它在iostr输入输出的格式控制C++提供了两种格式化输入/输出方式:一种是用ios类成员函数进行格式化输入输出另一种是用专门的操作符函数进行格式化输入输出1/4/202320第7章输入/输出流对象输入输出的格式控制C++提供了两种格式化输入/输出方式:1用ios类成员函数格式化ios类成员函数主要是通过对状态标志、输出宽度、填充字符以及输出精度的操作来完成输入/输出格式化。输入输出格式由各种状态标志来确定,这些状态标志在ios类中定义为枚举量。由于该枚举量定义在ios类中,因此引用时必须包含ios::前缀。使用时应该全部用符号名,绝不要用数值。1/4/202321第7章输入/输出流对象用ios类成员函数格式化ios类成员函数主要是通过对状态enum{ skipws=0x0001, //跳过输入空格 left=0x0002, //按左对齐格式输出 right=0x0004, //按右对齐格式输出 internal=0x0008, //输出符号和基指示符后的填补 dec=0x0010, //转换为十进制(In/Out) oct=0x0020, //转换为八进制(In/Out) hex=0x0040, //转换为十六进制(In/Out) showbase=0x0080, //输出显示基指示符 showpoint=0x0100, //输出显示小数点 uppercase=0x0200, //大写十六进制输出 showpos=0x0400, //正整数显示前加上“+” scientific=0x0800, //输出用科学表示法表示的浮点数 fixed=0x1000, //输出用固定小数点表示的浮点数 unitbuf=0x2000, //在输出操作后刷新所有流 stdio=0x4000 //在输出操作后刷新stdout和stderr}这些标志可以由ios类成员函数访问,也可以用操作符函数访问。1/4/202322第7章输入/输出流对象enum12/30/202222第7章输入/输出流对象用ios成员函数对状态标志进行操作ios类有3个成员函数可以对状态标志进行操作,分别为flags()、setf()和unsetf(),并且ios类还定义了一个long型数据成员记录当前状态标志。这些状态标志可用位或运算符“|”进行组合。用setf函数设置状态标志,其一般格式如下:

longios::setf(longflags)1/4/202323第7章输入/输出流对象用ios成员函数对状态标志进行操作ios类有3个成员函数可用ios成员函数对状态标志进行操作用unsetf函数清除状态标志,其一般格式如下:

longios::unsetf(longflags)用函数flags取状态标志有两种形式,其一般格式分别如下: longios::flags() longios::flags(longflag)

第一种形式返回与流相关的当前状态标志值;第二种形式将流的状态标志值设置为flag,并返回设置前的状态标志值。1/4/202324第7章输入/输出流对象用ios成员函数对状态标志进行操作用unsetf函数清除状态例使用ios成员函数操作状态字voidshowflags(longf);voidmain(){ longf; f=cout.flags();//取当前状态标志 showflags(f);//显示状态值 cout.setf(ios::showpos|ios::scientific|ios::fixed); //追加状态标志 f=cout.flags();//取当前状态标志 showflags(f);//显示状态值 cout.unsetf(ios::scientific);//从状态标志中去掉标志 f=cout.flags();//取当前状态标志 showflags(f);//显示状态值 f=cout.flags(ios::hex);//重新设置状态标志 showflags(f); f=cout.flags();//取当前状态标志 showflags(f);}1/4/202325第7章输入/输出流对象例使用ios成员函数操作状态字12/30/202225第7用ios成员函数设置输出宽度设置输出宽度函数有两种形式,其一般格式分别如下:

intios::width(intlen) intios::width() 第一种形式是设置输出宽度,并返回原来的输出宽度;第二种形式是返回当前输出宽度,输出宽度为0。1/4/202326第7章输入/输出流对象用ios成员函数设置输出宽度设置输出宽度函数有两种形式,其一例使用width控制输出宽度#include<iostream>usingnamesoacestd;intmain(){ doublevalues[]={1.23,35.36,653.7,4358.24};for(inti=0;i<4;i++){cout.width(10);cout<<values[i]<<'\n';}}输出结果:1.2335.36653.74358.241/4/202327第7章输入/输出流对象例使用width控制输出宽度输出结果:12/30/2022用ios成员函数设置填充字符填充字符的作用是当输出值不满输出宽度时用填充字符来填充,默认填充字符为空格。它与width()函数配合使用,否则没有意义。设置填充字符函数有两种形式,其格式分别如下:

charios::fill(charch)

charios::fill() 第一种形式是重新设置填充字符,并返回设置前的填充字符;第二种形式是返回当前的填充字符。1/4/202328第7章输入/输出流对象用ios成员函数设置填充字符填充字符的作用是当输出值不满输出例使用fill设置填充字符#include<iostream>usingnamesoacestd;intmain(){ doublevalues[]={1.23,35.36,653.7,4358.24};for(inti=0;i<4;i++){cout.width(10);cout.fill('*');cout<<values[i]<<'\n';}}输出结果:******1.23*****35.36*****653.7***4358.241/4/202329第7章输入/输出流对象例使用fill设置填充字符输出结果:12/30/20222用ios成员函数设置输出精度设置浮点数输出精度有两种形式,其格式分别如下:

intios::precision(intp) intios::precision() 第一种形式是重新设置输出精度,并返回设置前的输出精度;第二种形式是返回当前的输出精度。1/4/202330第7章输入/输出流对象用ios成员函数设置输出精度设置浮点数输出精度有两种形式,例使用precision设置填充字符#include<iostream>usingnamesoacestd;intmain(){ intj; j=cout.precision(); cout<<"presicion:"<<j<<endl; cout.precision(8); cout<<123.456789<<endl; cout<<"presicion:"<<cout.precision()<<endl;}输出结果:precision:6123.45679precision:81/4/202331第7章输入/输出流对象例使用precision设置填充字符输出结果:12/30/用操作符函数格式化输入输出除了专门的ios类成员函数,c++标准库还提供了标准的操作符函数专门操控这些状态。这组函数不属于任何类成员,定义在iomanip.h头文件中。将它们用在提取运算符“>>”或插入运算符“<<”后面来设定输入/输出格式,即在读写对象之间插入一个修改状态的操作。其中有些函数没有参数,所以又叫操作符。

1/4/202332第7章输入/输出流对象用操作符函数格式化输入输出除了专门的ios类成员函数,c+设置输入/输出宽度函数setw(int)设置输出填充字符函数setfill(int)设置输出精度函数setprecision(int)设置输入/输出整型数数制函数dec、hex和oct

取消输入结束符函数ws

控制换行操作符endl代表输出单字符“\0”的操作符ends1/4/202333第7章输入/输出流对象设置输入/输出宽度函数setw(int)12/30/2022例使用setw设置输入/输出宽度#include<iostream>#include<iomanip.h>usingnamesoacestd;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;}运行结果:123456781234567812345↙12345i:101/4/202334第7章输入/输出流对象例使用setw设置输入/输出宽度运行结果:12/30/20例分别用浮点、定点的方式表示一个实数#include<iostream>#include<iomanip.h>usingnamesoacestd;intmain(){ doublef=22.0/7; //在用浮点表示的输出中,setprecision(n)表示实数有效位数 cout<<f<<endl;//默认有效位数为6 cout<<setprecision(3)<<f<<endl;//最小的有效位数为3 //在用定点表示的输出中,setprecision(n)表示小数有效位数 cout<<setiosflags(ios::fixed); cout<<setprecision(8)<<f<<endl;//小数位数为8 return0;}运行结果:3.142863.143.142857141/4/202335第7章输入/输出流对象例分别用浮点、定点的方式表示一个实数运行结果:12/30/例使用dec、hex、oct设置输出整型数制#include<iostream>#include<iomanip.h>usingnamesoacestd;intmain(){ intnumber=1001; cout<<"Decimal:"<<dec<<number<<endl<<"Hexadecimal:"<<hex<<number<<endl<<"Octal:"<<oct<<number<<endl; return0;}运行结果:Decimal:1001Hexadecimal:3E9Ocatl:17511/4/202336第7章输入/输出流对象例使用dec、hex、oct设置输出整型数制运行结果:12用户自定义操作符函数c++提供了标准的操作符函数,也提供了建立自定义操作符函数的方法。建立输出操作符函数的格式如下: ostream&manip_name(ostream&stream) { <自定义语句序列> returnstream; }其中manip_name是自定义操作符函数的名字。1/4/202337第7章输入/输出流对象用户自定义操作符函数c++提供了标准的操作符函数,也提供了例用户自定义输出操作符函数#include<iostream>#include<iomanip.h>usingnamesoacestd;ostream&setup(ostream&stream){ stream.setf(ios::left); stream<<setw(10)<<setfill('$'); returnstream;}intmain(){ cout<<10<<""<<setup<<10<<endl; return0;}运行结果:1010&&&&&&&&1/4/202338第7章输入/输出流对象例用户自定义输出操作符函数运行结果:12/30/20223用户自定义操作符函数建立输入操作符函数的格式如下: istream&manip_name(istream&stream) { <自定义语句序列> returnstream; }其中manip_name是自定义操作符函数的名字。1/4/202339第7章输入/输出流对象用户自定义操作符函数建立输入操作符函数的格式如下:12/3例用户自定义输出操作符函数#include<iostream>#include<iomanip.h>usingnamesoacestd;istream&prompt(istream&stream){cin>>hex;cout<<"Enternumberusinghexformat:";returnstream;}intmain(){ inti; cin>>prompt>>i; cout<<i<<endl; return0;}运行结果:Enternumberusinghexformat:ff↙2551/4/202340第7章输入/输出流对象例用户自定义输出操作符函数运行结果:12/30/20224自定义类型对象的输入/输出上面都是对基本类型数据进行输入/输出操作,实际上,C++允许对自定义类型对象进行同样简单语法的输入/输出。示例自定义类型对象的输入/输出 1/4/202341第7章输入/输出流对象自定义类型对象的输入/输出上面都是对基本类型数据进行输入/classDate{public: Date(inty,intm,intd){Year=y;Month=m;Day=d;} friendostream&operator<<(ostream&stream,Date&date); friendistream&operator>>(istream&stream,Date&date);private: intYear,Month,Day;};ostream&operator<<(ostream&stream,Date&date){stream<<date.Year<<"/"<<date.Month<<"/"<<date.Day<<endl; returnstream;}istream&operator>>(istream&stream,Date&date){ stream>>date.Year>>date.Month>>date.Day; returnstream;}1/4/202342第7章输入/输出流对象classDate12/30/202242第7章输入/输出intmain(){ Datedate(2005,11,28); cout<<"Currentdate:"<<date<<endl; cout<<"Enternewdate:"; cin>>date; cout<<"Newdate:"<<date<<endl; return0;}输出结果为:Currentdate:2005/11/28Enternewdate:2007129↙Newdate:2007/12/91/4/202343第7章输入/输出流对象intmain()12/30/202243第7章输入/输出文件的输入/输出如何对文本文件和二进制文件进行输入和输出操作?1/4/202344第7章输入/输出流对象文件的输入/输出如何对文本文件和二进制文件进行输入和输出操文件的概念

文件一般指的是磁盘文件,它是存储在磁盘上的相关数据集合。每个文件都有确定的名字。需要长久保存并能够被重新读写的信息,将它保存在外存文件上。C++常用的文件有程序文件,数据文件以及设备文件。键盘作为标准输入文件,显示器作为标准输出文件。C++标准库提供了相关的文件操作。对需要输入的大批量数据,可以事先以文件的形式存放在磁盘上,在程序中,从指定的文件中读取数据;程序的运行结果也可以写入磁盘上指定的文件,使用时再将文件中的数据读入。1/4/202345第7章输入/输出流对象文件的概念文件一般指的是磁盘文件,它是存储在磁盘上的相关C++把文件看作是一个字符(字节)的序列,即由一个个字符(字节)数据顺序组成。文件按存储格式分二类:一种为字符格式文件,简称字符文件(ASCII码文件或文本文件),另一种为内部格式文件,简称字节文件(二进制文件)字符文件中,每一个字节单元的内容存放一个字符的ASCII码,能够直接被显示和打印。字节文件中,是把内存中的数据按其在内存中的存储形式原样输出到磁盘文件存放。1/4/202346第7章输入/输出流对象C++把文件看作是一个字符(字节)的序列,即由一个个字符(字两种文件的比较ASCII码文件占用字节多,把内存中的数据写入ASCII码文件或从ASCII码文件读数据存放在内存中,需要转换。二进制文件占用字节少,把内存中的数据写入二进制文件或从二进制文件读数据存放在内存中,不需要转换。 例如:10000是整型数据,用二进制表示占两或四个字节,如用ASCII码表示,则占五个字节。对于字符信息,在字符文件和字节文件中保存的信息是相同的。对于数值信息,在字符文件和字节文件中保存的信息是不同的。1/4/202347第7章输入/输出流对象两种文件的比较ASCII码文件占用字节多,把内存中的数据写入文件操作要在程序中使用文件,首先应在文件开始包含头文件:

#include<fstream>在访问文件之前,用头文件fstream中提供的输入文件流类ifstream、输出文件流类ofstream或输入输出文件流类fstream定义一个文件流类的对象,然后用该对象调用相应类中的open成员函数,按照一定的打开方式打开一个文件。文件被打开后,就可以通过文件流对象访问它。文件访问结束后,再通过流对象关闭它,释放缓冲区。1/4/202348第7章输入/输出流对象文件操作要在程序中使用文件,首先应在文件开始包含头文件:12文件操作的一般步骤

为文件定义一个流类对象;使用open()函数建立(或打开)文件。如果文件不存在,则建立该文件;如果磁盘上已存在该文件,则打开该文件;进行读写操作。在建立(或打开)的文件上执行所要求的输入/输出操作。一般来说,在内存与外设的数据传输中,由内存到外设称为输出或写,反之则称为输入或读;使用close()函数关闭文件。当完成操作后,应把打开的文件关闭,避免误操作。1/4/202349第7章输入/输出流对象文件操作的一般步骤为文件定义一个流类对象;12/30/20文件的打开每个文件流类都有一个open成员函数,并且具有完全相同的声明格式,具体声明格式为:

voidopen(constchar*fname,intmode,intaccess); 其中,fname指向要打开文件的文件名字符串,mode指定打开文件的方式,对应的实参是ios类中定义的open_mode枚举类型中的枚举常量,或由这些枚举常量构成的按位或表达式,access指定文件的访问方式。在C++中,打开一个文件就是将这个文件与对应流对象建立关联;1/4/202350第7章输入/输出流对象文件的打开每个文件流类都有一个open成员函数,并且具有完全1/4/202351第7章输入/输出流对象12/30/202251第7章输入/输出流对象定义文件流对象和打开文件举例:1)ofstreamfout; fout.open(“a:\\data1.dat”);2)ifstreamfin;fin.open(“a:\\data1.dat”,ios::in|ios::nocreat);3)ofstreamofs;ofs.open(“a:\\data1.dat”,ios::app);4)fstreamfio;fio.open(“a:\\data1.dat”,ios::out|ios::binary);1/4/202352第7章输入/输出流对象定义文件流对象和打开文件举例:12/30/202252第7章文件的关闭每个文件流类中都提供有一个关闭文件的成员函数close,当打开的文件操作结束后,就需要关闭它,使文件流与对应的物理文件断开联系。关闭任何一个流对象所对应的文件,就是用这个流对象调用close成员函数。文件流对应的文件被关闭后,还可以利用该文件流调用open成员函数打开其他的文件。

ofstreamfout; fout.open(“a:\\data1.dat”); …… fout.close();1/4/202353第7章输入/输出流对象文件的关闭每个文件流类中都提供有一个关闭文件的成员函数clo文件指针

对于每个打开的文件,都存在着一个文件指针,初始指向一个隐含的位置,该位置由具体打开方式决定。 对文件的读写都是从当前文件指针所指的位置开始,在读写过程中,文件指针顺序后移。文件的结束标志 每个文件都有一个结束标志。当文件指针移到文件的结束标志处时,表示文件结束。1/4/202354第7章输入/输出流对象文件指针12/30/202254第7章输入/输出流对象测试文件是否结束,常用的方法有两种:

1.ASCII码文件的结束标志用“-1”表示。C++在ios类中用符号常量“EOF”表示-1,当读取到的字符等于文件结束符EOF时表示文件访问结束。 2.C++还提供了使用流对象调用eof()成员函数来测试文件当前状态是否“文件结束”。如果eof()的值是非0值,表示文件结束;如果eof()的值是0,则表示文件没有结束。用该方法测试的文件既可以是ASCII码文件又可以是二进制文件。1/4/202355第7章输入/输出流对象测试文件是否结束,常用的方法有两种:12/30/202255字符文件的访问操作向字符文件输出数据 指依次把数据写入到文件的末尾(文件结束符也随之后移,它始终占据整个文件空间的最后一个字节位置)。从字符文件输入数据 指从文件开始位置起依次向后提取数据,直到碰到文件结束符为止。1/4/202356第7章输入/输出流对象字符文件的访问操作向字符文件输出数据12/30/202256字符文件的访问操作向字符文件输出数据 调用从ostream流类中继承来的插入操作符重载函数。 调用从ostream流类中继承来的put成员函数。 声明格式如下:

ostream&operator<<(简单类型); ostream&put(char);1/4/202357第7章输入/输出流对象字符文件的访问操作向字符文件输出数据12/30/202257字符文件的访问操作从字符文件输入数据 调用提取操作符重载成员函数,每次从文件流中提取用空白符隔开的一个数据。 调用get成员函数,每次从文件流中提取一个字符并作为返回值返回。 调用getline成员函数,每次从文件流中提取一行字符到字符指针所指向的存储空间中。 可以在istream文件中找到上述成员函数声明。1/4/202358第7章输入/输出流对象字符文件的访问操作从字符文件输入数据12/30/202258例字符文件的读写#include<iostream>#include<fstream>usingnamespacestd;intmain(){ chars1[8],s2[8]; fstreamoutfile; cin>>s1; outfile.open(“exam.txt”,ios::out); if(!outfile) { cout<<“exam.txtcan’topen”<<endl; } outfile<<s1; outfile.close(); outfile.open(“exam.txt”,ios::in); outfile>>s2; cout<<s2<<endl; outfile.close(); return0;}运行结果:abcd↙abcd1/4/202359第7章输入/输出流对象例字符文件的读写运行结果:12/30/202259第7章输字节文件的访问操作字节文件是指在打开方式中带有ios::binary选项的文件。向字节文件输出数据 把内存中由指定字符指针所指向的具有一定字节数的内容原原本本地写入到文件中,文件指针后移。从字节文件输入数据 把具有一定字节数的内容原原本本地拷贝到内存中由指定字符指针所指向的存储空间中,文件指针后移。1/4/202360第7章输入/输出流对象字节文件的访问操作字节文件是指在打开方式中带有ios::bi字节文件的访问操作通过文件流对象调用在istream流类中定义的read成员函数能够从文件流对象所对应的文件中读出信息。通过文件流对象调用在ostream流类中定义的write成员函数能够向文件流对象所对应的文件中写入信息。这两个成员函数的声明格式如下:

istream&read(char*buffer,intlen); ostream&write(constchar*buffer,intlen);1/4/202361第7章输入/输出流对象字节文件的访问操作通过文件流对象调用在istream流类中定例字节文件的读写#include<iostream>#include<fstream>usingnamespacestd;structperson{ charname[20]; doubleheight; unsignedshortage;}people[4]={“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(); }1/4/202362第7章输入/输出流对象例字节文件的读写12/30/202262第7章输入/输出流 for(inti=0;i<4;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<4;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;}运行结果:wang 1.65 25zhang 1.78 24Li 1.85 21 0 01/4/202363第7章输入/输出流对象 for(inti=0;i<4;i++)运行结果:12/3文件的随机读写C++文件都是流文件,随机文件的读写与文件指针相关,文件指针记录着文件流的当前位置。有3个成员函数能对文件指针进行操作:

istream&istream::seekg(<流文件中位置>);

istream&istream::seekp(<偏移量>,<参照位置>); streamposistream::tellg(); 其中,streampos被定义为long型量,<流文件中位置><偏移量>都是long型量,并以字节为单位。<参照位置>具有如下含义: ios:cur,相对于当前读指针所指定的位置; ios:beg,相对于流的开始位置; ios:end,相对于流的结尾处;1/4/202364第7章输入/输出流对象文件的随机读写C++文件都是流文件,随机文件的读写与文件指针例文件的随机读写#include<iostream>#include<fstream>usingnamespacestd;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));

1/4/202365第7章输入/输出流对象例文件的随机读写12/30/202265第7章输入/输出流 file.seekg(pos); file.read((char*)&i,sizeof(int)); cout<<“thedatastoredis”<<i<<endl; file.seekp(0,ios::beg); for(i=80;i<100;i++) file.write((char*)&i,sizeof(int)); file.seekg(pos); file.read((char*)&i,sizeof(int)); cout<<“thedatastoredis”<<i<<endl; file.seekg(20,ios::cur); file.read((char*)&i,sizeof(int)); cout<<“thedatastoredis”<<i<<endl; cout<<“currentbytenumber:”<<file.tellg()<<endl; return0;}seekg就是seekget,seekp是seekput,前者用于ifstream对象,后者用于ofstream对象,但是在ftream对象里,两者没有区别。运行结果:currentbytenumber:60thedatastoredis15thedatastoredis95thedatastoredis21currentbytenumber:881/4/202366第7章输入/输出流对象 file.seekg(pos);运行结果:12/30/20下面程序用istream和ostream类的操作符对点数据进行文件操作,从键盘上输入两个点的坐标,把它保存到磁盘文件上,并从磁盘上读出数据,输出到显示器上。#include<iostream>#include<fstream>usingnamesoacestd;classPoint{public: Point(intx,inty){X=x;Y=y;} friendostream&operator<<(ostream&os,Point&aPoint); friendistream&operator>>(istream&is,Point&aPoint);protected: intX; intY;};1/4/202367第7章输入/输出流对象下面程序用istream和ostream类的操作符对点数据进ostream&operator<<(ostream&os,Point&aPoint){ os<<"("<<aPoint.X<<","<<aPoint.Y<<")"; returnos;}istream&operator>>(istream&is,Point&aPoint){ is>>“(">>aPoint.X>>",">>aPoint.Y>>")"; returnis;}intmain(){ intx,y; ofstreamwritefile("crest.sav"); if(!writefile) { cout<<"Can'topenfile"; exit(-1); }1/4/202368第7章输入/输出流对象ostream&operator<<(ostream&o cout<<"inputthex,ywithblankseperated:"; cin>>x>>y; PointPoint1(x,y); cout<<"inputx,yofanotherpoint"; cin>>x>>y; PointPoint2(x,y); writefile<<Point1; writefile<<Point2; writefile.close(); ifstreamreadfile("ctest.sav"); if(!readfile) {cout<<"Cannotopenfile";exit(-1); } readfile>>Point1>>Point2; cout<<Point1<<endl; cout<<Point2<<endl; return0;}1/4/202369第7章输入/输出流对象 cout<<"inputthex,ywithbla字符串流C++支持内存中的输入输出,只要将流对象与存储在内存中的char*或string捆绑起来即可。针对char*和string两种类型的对象,C++提供了两种字符串流,一种在<sstream>中定义,另一种在<strstream>中定义,两者功能基本相同。<strstream>包含istrstream,ostrstream和strstream,是基于C风格字符串char*编写的。<sstream>包含istringstream,ostringstream和stringstream等类,是基于C++中std::string编写的。1/4/202370第7章输入/输出流对象字符串流C++支持内存中的输入输出,只要将流对象与存储在内存字符串流一个字符串流被定义后就可以调用相应的成员函数进行数据的输入、输出操作。对字符串流的操作方法通常与对字符文件流的操作方法相同。字符串流对应的访问空间是内存中由用户定义的字符数组,对字符串流的操作实质上就是在该数组上进行的。与文件流不同,字符串流对应的字符数组中没有相应的结束符标志,用户可以规定一个特殊字符作为其结束符使用。1/4/202371第7章输入/输出流对象字符串流一个字符串流被定义后就可以调用相应的成员函数进行数据例字符串流对象的读写#include<iostream>#include<sstream>#include<string>usingnamespacestd;intmain(){ stringstreamostr("ccc"); ostr.put('d'); ostr.put('e'); ostr<<"fg"; stringgstr=ostr.str(); cout<<gstr<<endl; chara; ostr>>a; cout<<a<<endl; return0;}运行结果:defgd1/4/202372第7章输入/输出流对象例字符串流对象的读写运行结果:12/30/202272第7例字符串流对象用于类型转换#include<iostream>#include<sstream>#include<string>usingnamespacestd;intmain(){ stringstreamsstr; inta=100; stringstr; sstr<<a; sstr>>str; cout<<str<<endl; sstr.clear();//每一次转换后必须调用clear()成员函数 stringname="colinguan"; charcname[200]; sstr<<name; sstr>>cname; cout<<cname<<endl; return0;}运行结果:100colinguan1/4/202373第7章输入/输出流对象例字符串流对象用于类型转换运行结果:12/30/20227小结C++标准库提供了一组类簇来处理输入输出: iostream类处理面向流的输入输出; fstream类处理面向文件的输入输出; stringstream类处理内存中字符串的输入输出;所有这些类都是通过继承相互关联的,输入类继承了istream,输出类继承了ostream,输入输出类继承了iostream,可在基类对象上执行的操作同样适用于派生类对象。1/4/202374第7章输入/输出流对象小结C++标准库提供了一组类簇来处理输入输出:12/30/2《面向对象程序设计》七、输入/输出流对象1/4/202375第7章输入/输出流对象《面向对象程序设计》七、输入/输出流对象12/30/2022内容提要螺旋矩阵的输入/输出问题流无格式输入/输出输入/输出的格式控制自定义类型对象的输入输出文件的输入/输出问题1/4/202376第7章输入/输出流对象内容提要螺旋矩阵的输入/输出问题12/30/20222提出问题编程输出M*M的螺旋矩阵,要求数据间距与M相同。例如,4*4的螺旋矩阵,其间距为4:

123412131451116156109871/4/202377第7章输入/输出流对象提出问题编程输出M*M的螺旋矩阵,要求数据间距与M相同。例如分析问题C++没有定义任何用于执行输入或输出的语句,但可以使用C语言中的标准I/O函数printf()和scanf()来解决此问题。1/4/202378第7章输入/输出流对象分析问题C++没有定义任何用于执行输入或输出的语句,但可以使【例】有如下程序:#include<stdio.h>intb=20;floata=5.6;intmain(){printf("%d\n",a);scanf("%d",&a);scanf("%d",&b);printf("%d\n","abc");return0;}该程序的运行结果为:161061273623↙45↙43499801/4/202379第7章输入/输出流对象【例】有如下程序:该程序的运行结果为:12/30/20225printf()与scanf()存在以下两个缺点:1.非类型安全2.不可扩充性classA{…}Aa;…printf("%?",a);//不知用什么格式符来识别A的对象1/4/202380第7章输入/输出流对象printf()与scanf()存在以下两个缺点:12/30C++用I/O流来解决这个问题。下面先介绍流的概念。1/4/202381第7章输入/输出流对象C++用I/O流来解决这个问题。12/30/20227第7章流的概念在C++程序中,数据可以从外部设备(键盘等)流入到计算机内存中,也可以从计算机内存流向外部设备(屏幕或磁盘文件等),这种数据传递被称作输入输出。C++将数据从一个位置到另一个位置的传递抽象为流。所谓流(stream)就是指数据从一个位置流向另一个位置。流是字节的序列。C++的输入输出操作是基于流来处理的。1/4/202382第7章输入/输出流对象流的概念在C++程序中,数据可以从外部设备(键盘等)流入到I/O流操作C++基于流的概念处理数据的输入输出,因此也称之为输入输出流,即I/O流。I/O流具有两个基本的行为特征,一是从流中获取数据的操作称为提取操作,二是向流中添加数据的操作称为插入操作。1/4/202383第7章输入/输出流对象I/O流操作C++基于流的概念处理数据的输入输出,因此也称之I/O流类C++标准库围绕流的概念,提供了一整套I/O流类簇,既可用于标准类型数据的I/O,也能用于自定义类型对象的I/O,这种扩展性是C++最有价值的特点之一。C++标准库提供的I/O流类的各种操作都是类型安全(typesafe)的。不同类型的I/O流操作都是重载的,没有定义过I/O功能的类型不具备I/O操作的能力。1/4/202384第7章输入/输出流对象I/O流类C++标准库围绕流的概念,提供了一整套I/O流类簇I/O流类簇的层次结构C++标准库提供的I/O流类簇有两个平行基类:streambuf(filebuf,stringbuf,strstreambuf)ios(istream,ostream)ios类有下面直接派生类:输入流类istream (ifstream,istringstream,istrstream)输出流类ostream (ofstream,ostringstream,ostrstream)(iostream->fstream,stringstream,strstream)1/4/202385第7章输入/输出流对象I/O流类簇的层次结构C++标准库提供的I/O流类簇有两个I/O流分类C++标准库提供的I/O流按功能可分为如下3类:标准I/O流:内存与标准输入输出设备(键盘、屏幕)之间数据的传递;文件I/O流:内存与外部磁盘文件之间数据的传递;字符串I/O流:内存变量与表示字符串流的字符数组之间数据的传递。1/4/202386第7章输入/输出流对象I/O流分类C++标准库提供的I/O流按功能可分为如下3类:标准I/O流对象标准I/O流预定义了4个流类对象:cin、cout、cerr、clog。操作系统给把外设用文件名的方式进行管理,因此程序设计要访问外设就跟访问文件一样方便。

1/4/202387第7章输入/输出流对象标准I/O流对象标准I/O流预定义了4个流类对象:cin、cI/O分为无格式支持的低级I/O和具有格式支持的高级I/O。无格式支持的低级I/O以基本字节为操作对象,有格式支持的高级I/O把若干字节组合成有意义的单位,如整数、浮点数、字符、字符串及用户自定义类型等等。1/4/202388第7章输入/输出流对象I/O分为无格式支持的低级I/O和具有格式支持的高级I/O。无格式输入/输出无格式输入/输出就是按系统预定义的格式进行的输入/输出。按默认约定,每个C++程序都能使用标准I/O流,如标准输入、标准输出。cin用来处理标准输入,即键盘输入;cout用来处理标准输出,即屏幕输出。它们被定义在iostream头文件中。在使用cout和cin前,要用编译预处理命令将所使用的头文件包含到源程序中,其格式如下:

#include<iostream>1/4/202389第7章输入/输出流对象无格式输入/输出无格式输入/输出就是按系统预定义的格式进行无格式输出“<<”是预定义的插入运算符,作用在流类对象cout上,实现默认格式的屏幕输出。使用cout输出表达式值到屏幕上的格式如下:

cout<<E1<<E2<<…<<Em; 其中,E1、E2、…、Em为均为表达式。功能是计算各表达式的值,并将结果输出到屏幕当前光标位置处。1/4/202390第7章输入/输出流对象无格式输出“<<”是预定义的插入运算符,作用在流类对象co无格式输出cout是ostream流类的对象,它在iostream头文件中作为全局对象定义,其格式如下: ostreamcout(stdout); 其中,stdout表示标准输出设备名(屏幕)。在ostream流类中,对应每个基本数据类型定义运算符“<<”重载函数为友元,它们在ostream中声明:ostream&operator<<(ostream&dest,char*pSource);ostream&operator<<(ostream&dest,intsource);ostream&operator<<(ostream&dest,charsource);1/4/202391第7章输入/输出流对象无格式输出cout是ostream流类的对象,它在iost无格式输入“>>”是预定义的提取运算符,作用在流类对象cin上,实现默认格式的键盘输入。使用cin将数据输入到变量的格式如下:

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

其中,V1、V2、…、Vn都是变量。功能是暂停执行程序,等待用户从键盘输入数据,各数据间用空格或Tab键分隔,输入数据类型要与接受变量类型一致,输完后,按回车键结束。1/4/202392第7章输入/输出流对象无格式输入“>>”是预定义的提取运算符,作用在流类对象ci无格式输入cin是istream流类的对象,它在iostream头文件中作为全局对象定义,其格式如下: istreamcin(stdin);在istream流类中,对应每个基本数据类型定义运算符“>>”重载函数为友元,它们在istream中声明: istream&operator>>(istream&sour,char*pDes); istream&operator>>(istream&sour,intdes); istream&operator>>(istream&sour,chardes);1/4/202393第7章输入/输出流对象无格式输入cin是istream流类的对象,它在iostr输入输出的格式控制C++提供了两种格式化输入/输出方式:一种是用ios类成员函数进行格式化输入输出另一种是用专门的操作符函数进行格式化输入输出1/4/202394第7章输入/输出流对象输入输出的格式控制C++提供了两种格式化输入/输出方式:1用ios类成员函数格式化ios类成员函数主要是通过对状态标志、输出宽度、填充字符以及输出精度的操作来完成输入/输出格式化。输入输出格式由各种状态标志来确定,这些状态标志在ios类中定义为枚举量。由于该枚举量定义在ios类中,因此引用时必须包含ios::前缀。使用时应该全部用符号名,绝不要用数值。1/4/202395第7章输入/输出流对象用ios类成员函数格式化ios类成员函数主要是通过对状态enum{ skipws=0x0001, //跳过输入空格 left=0x0002, //按左对齐格式输出 right=0x0004, //按右对齐格式输出 internal=0x0008, //输出符号和基指示符后的填补 dec=0x0010, //转换为十进制(In/Out) oct=0x0020, //转换为八进制(In/Out) hex=0x0040, //转换为十六进制(In/Out) showbase=0x0080, //输出显示基指示符 showpoint=0x0100, //输出显示小数点 uppercase=0x0200, //大写十六进制输出 showpos=0x0400, //正整数显示前加上“+” scientific=0x0800, //输出用科学表示法表示的浮点数 fixed=0x1000, //输出用固定小数点表示的浮点数 unitbuf=0x2000, //在输出操作后刷新所有流 stdio=0x4000 //在输出操作后刷新stdout和stderr}这些标志可以由ios类成员函数访问,也可以用操作符函数访问。1/4/202396第7章输入/输出流对象enum12/30/202222第7章输入/输出流对象用ios成员函数对状态标志进行操作ios类有3个成员函数可以对状态标志进行操作,分别为flags()、setf()和unsetf(),并且ios类还定义了一个long型数据成员记录当前状态标志。这些状态标志可用位或运算符“|”进行组合。用setf函数设置状态标志,其一般格式如下:

longios::setf(longflags)1/4/202397第7章输入/输出流对象用ios成员函数对状态标志进行操作ios类有3个成员函数可用ios成员函数对状态标志进行操作用unsetf函数清除状态标志,其一般格式如下:

longios::unsetf(longflags)用函数flags取状态标志有两种形式,其一般格式分别如下: longios::flags() longios::flags(longflag)

第一种形式返回与流相关的当前状态标志值;第二种形式将流的状态标志值设置为flag,并返回设置前的状态标志值。1/4/202398第7章输入/输出流对象用ios成员函数对状态标志进行操作用unsetf函数清除状态例使用ios成员函数操作状态字voidshowflags(longf);voidmain(){ longf; f=cout.flags();//取当前状态标志 showflags(f);//显示状态值 cout.setf(ios::showpos|ios::scientific|ios::fixed); //追加状态标志 f=cout.flags();//取当前状态标志 showflags(f);//显示状态值 cout.unsetf(ios::scientific);//从状态标志中去掉标志 f=cout.flags();//取当前状态标志 showflags(f);//显示状态值 f=cout.flags(ios::hex);//重新设置状态标志 showflags(f); f=cout.flags();//取当前状态标志 showflags(f);}1/4/202399第7章输入/输出流对象例使用ios成员函数操作状态字12/30/202225第7用ios成员函数设置输出宽度设置输出宽度函数有两种形式,其一般格式分别如下:

intios::width(intlen) intios::width() 第一种形式是设置输出宽度,并返回原来的输出宽度;第二种形式是返回当前输出宽度,输出宽度为0。1/4/2023100第7章输入/输出流对象用ios成员函数设置输出宽度设置输出宽度函数有两种形式,其一例使用width控制输出宽度#include<iostream>usingnamesoacestd;intmain(){ doublevalues[]={1.23,35.36,653.7,4358.24};for(inti=0;i<4;i++){cout.width(10);cout<<values[i]<<'\n';}}输出结果:1.2335.36653.74358.241/4/2023101第7章输入/输出流对

温馨提示

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

评论

0/150

提交评论