第七章 I/O流
§7—1 流的概念 1.C++语言无输入/输出语句 2.C++完全支持C的I/O系统
4.C的I/O系统格式繁琐,不同库函数在参数次序和语义方面不一致,不安全。且不同类型的数据采用不同的格式控制字符,难记 5.C++编译系统带有一个面向对象的I/O软件包,即I/O流类库,它不是C++语言的组成部分
6.流是一种抽象数据类型,它负责在数据的生产者和数据的消费者之间建立联系,并管理数据的流动 7.从流中获取(读入)数据的操作称为提取操作,向流中添加(输出)数据的操作称为插入操作 8.C++的I/O流可以根据数据类型,自动使用合适的输出方式
§7—2 流类库 一、I/O流类库基本结构 streambuf ios istream ostream iostream ios为虚基类 §7—2 流类库 一、I/O流类库基本结构 streambuf ios istream ostream iostream ios为虚基类 ios streambuf istream ostream iostream
二、文件流类 ① fstreambase:公共基类,从ios类派生的 ② ifstream:从istream类和fstreambase类派生的 ③ ofstream:从ostream类和fstreambase类派生的 ④ fstream: 从iostream类和fstreambase类派生的 ⑤ filebuf: 从streambuf类派生的
三、字符串流类 ① strstreambase类 ② istrstream类 ③ ostrstream类 ④ strstream类 ⑤ strstreambuf类
四、加载类库 使用上述类时应包含iostream.h文件或fstream.h文件或strstrea.h文件
五、在iostream.h文件中预定义了 4个流对象 ① cin:是istream类的全局对象,标准输入,即键盘输入 ② cout:是ostream类的全局对象,用于处理标准输出,即屏幕输出 ③ cerr:是ostream类的对象,用于处理标准错误信息,屏幕输出,没有缓冲,发送给它的内容立即被输出 ④ clog:是ostream类的对象,用于处理标准错误信息,打印机输出,有缓冲,缓冲区满时被输出
§7—3 I/O流 一、屏幕输出 1.使用系统预定义的插入符“<<”,可以连续串接多个以输出多个数据项目 2.插入运算符后面为表达式时,应注意优先级以保证先计算表达式的值再输出
3.可使用流类库中提供的成员函数put( )来输出一个字符 ostream & cout.put(char c); 或ostream & cout.put(const char c); 也可以串接多个put( )函数来输出多个字符 4.可使用流类库中提供的成员函数write( )来输出一个字符串 cout.write(const char * str, int n);
二、键盘输入 1.预定义的提取符“>>”可以连用,以读取多个数据项,各输入数据项间以空格符分隔 2.可使用流类库中的成员函数get( )来获取一个字符 char istream::get( );
3.可使用流类库中的成员函数getline( )来获取一行字符 cin.getline(char * buf, int n, deline='\n'); 结束该函数的条件: ① 读完n-1个字符后 ② 读到换行符 ③ 读到文件结束符或输入流结束符 4.可使用istream类的成员函数read( )来读取若干字符 cin.read(char * buf, int size);
三、格式化I/O 1.控制格式I/O的方法有两种 ① 用成员函数 ② 用格式控制符 2.用成员函数进行格式输出 ① 先用某些成员函数来设置格式标志位 ② 再用另一些成员函数进行格式输出
3.格式标志位 left(左对齐)、right(右对齐)、dec(十进制)、oct(八进制)、hex(十六进制)、scientific(浮点数)、fixed(定点数)、showbase(数前显示基数符号) 4.设置格式标志位的成员函数 long flags( ); long flags(long); long setf(long setbits, long field) long setf(long) long unsetf(long)
5.控制格式输出的成员函数 int width( ); int width(int); char fill(); char fill(char); int precision(); int precision (int);
6.用格式控制符进行格式输出 dec(十进制)、oct(八进制)、hex(十六进制)、setbase(int n)设置基数、setfill(int)设置填充字符、setw(int)设置域宽 此时应包含头文件:iomanip.h
四、文件I/O 1.打开文件的方法有两种 (1)方法一 fstream 对象名; 对象名.open("文件名", 方式);
(2)方法二 ①打开写文件 ofstream 对象名; 对象名.open("文件名"); 或ofstream 对象名("文件名"); ②打开读文件 ifstream 对象名; 或ifstream 对象名("文件名");
2.关闭文件 流对象名.close( ); 3.文件访问方式常量 in(读)、out(写)、app(追加)、ate(打开时,文件指针位于文件尾)、binary(二进制)、ios::inlios::out(以读和写方式)
五、字符串I/O 1.ostrstream类: ①重载构造函数 ostrstream::ostrstream( ); ostrstream::ostrstream(const char *str, int size, int mode=ios::out); ②两个成员函数 int ostrstream::pcount( ); char *ostrstream::str( );
2.istrstream类的重载构造函数 istrstream::istrstream(char * str); istrstream::istrstream(char * str, int n);
for(ch='A'; ch<='F'; ch++) cout.put(ch); #include "iostream.h" # include "string.h" void main() {char ch; for(ch='A'; ch<='F'; ch++) cout.put(ch); cout.put('\n').put('a').put('b').put('c').put('\n'); char * p="ABCDEF"; cout.write(p,strlen(p)).put('\n'); cout.write(p,3)<<'\n'; } 结果: ABCDEF abc ABC
# include "iostream.h" void main() {char ch; cout<<"Input:\n"; while((ch=cin.get())!=EOF) cout.put(ch); } 运行: Input: 12345↙ 12345 <Ctrl+z>
cout<<"Input1:\n"; cin.getline(buf,SIZE); cout.write(buf,SIZE); # include "iostream.h" const int SIZE=80; void main() {char buf[SIZE]=""; cout<<"Input1:\n"; cin.getline(buf,SIZE); cout.write(buf,SIZE); cout<<"\nInput2:\n"; cin.read(buf, SIZE); cout.put('\n')<<buf<<endl; } 运行: Input1: 12345↙ 12345 Input2: abcdef ↙<Ctrl+z> abcdef press any key to continue
# include "iostream.h" # include "iomanip.h" void main() {cout.setf(ios::hex,ios::basefield); cout<<"HEX:"<<60<<endl; cout.setf(ios::showbase); cout<<"hex:"<<47<<endl; cout.setf(ios::oct,ios::basefield); cout<<"OCT:"<<62<<endl; cout.width(10); cout<<dec<<12345<<endl; cout.fill('#'); cout.setf(ios::left, ios::adjustfield); cout<<12345<<endl; cout.setf(ios::right,ios::adjustfield); cout.precision(4); cout<<12.34567<<endl; cout<<setw(10)<<12345<<endl; cout<<setiosflags(ios::left)<<setfill('*')<<setprecision(4)<<setw(8)<<12.34567<<endl; } 结果: HEX:3C hex:ox2f OCT:076 12345 12345##### 12.35 #####12345 12.35***
{for(int i=3; i>1; i--) # include "iostream.h" # include "iomanip.h" void main() {for(int i=3; i>1; i--) cout<<setfill(' ')<<setw(i)<<" "<<setfill('*')<<setw(7-2*i)<<"*"<<endl; for(i=1; i<4; i++) } 结果: * *** *****
# include "iostream.h" # include "fstream.h" # include "stdlib.h" void main() {fstream of; of.open("f1.dat",ios::out); if(!of){cout<<"f1.dat can't open.\n";abort();} of<<"AAAA\n"; of<<"BBBB\n"; of<<"CCCC\n"; of.close(); cout<<"end…\n"; fstream inf; inf.open("f1.dat", ios::in); if(!inf){cout<<"f1.dat can't open.\n";abort();} char p[80]; while (!inf.eof()){inf.getline(p, sizeof(p));cout<<p<<endl;} inf.close(); } 结果: end… AAAA BBBB CCCC
# include "iostream.h" # include "fstream.h" # include "strstrea.h" void main() {char buf[]="54321"; int i,j; istrstream s1(buf),s2(buf,1); s1>>i; s2>>j; cout<<i<<"**"<<j<<endl; char buffer[80]; ostrstream s3(buffer, sizeof(buffer)); for(i=0; i<5; i++) s3<<'#'<<i<<'#'; s3<<'\0'; cout<<"BUFFER:"<<buffer<<endl; } 结果: 54321**5 BUFFER:#0##1##2##3##4#
§7—4 插入符和提取符的重载 1.用户可通过对插入符“<<”和提取符“>>”进行重载,来支持自定义数据类型的输入和输出 2.重载函数的返回类型应是ostream或istream类的对象引用,以保证插入符和提取符的连续使用 3.使流I/O可扩展,重载函数只能是非成员函数
4.重载的插入符和提取符函数,不能是所操作类的成员函数,可以是全局函数或该类的友元函数 5.重载插入符的格式: ostream & operator<<(ostream & out,usertypename objectname) {//out<<objectname.item;操作代码 return out; } 注意:第二个参数可以不是引用类型
6.重载提取符的格式: istream & operator>>(istream & in,usertypename & objectname) {//in>>objectname.item;操作代码 return in; } 注意:第二个参数也必须是引用类型
# include "iostream.h" class A {public: A(int i=0,int j=0){x=i; y=j;} int x, y; }; ostream & operator<<(ostream & str, A a) {str<<a.x<<"**"<<a.y<<endl; return str;} istream & operator>>(istream & s, A & b) {cout<<"Input:";s>>b.x>>b.y; return s;} void main() {A m, n(2,3); cout<<n; cin>>m; cout<<m; } 结果: 2**3 Input:4 5↙ 4**5
# include "iostream.h" class A {public: A(int i, int j):x(i), y(j){} void output(){cout<<x<<y<<endl;} void input(){cin>>x>>y;} private: int x, y; }; ostream & operator<<(ostream & out, A & a) {a.output(); return out;} istream & operator>>(istream & in, A & b) {b.input(); return in;} void main() {A m(2,3), n(4,5); cout<<m<<n; cin>>m>>n; } 运行: 23 45 6 7↙ 8 9↙ 67 89
# include "iostream.h" class A {public: A(int i, int j):x(i), y(j){} friend ostream & operator<<(ostream &,A); friend istream & operator>>(istream &, A &); private: int x, y; }; ostream & operator<<(ostream & out, A a) {out<<a.x<<"**"<<a.y<<endl; return out;} istream & operator>>(istream & in, A & b) {cout<<"Input:";in>>b.x>>b.y; return in;} void main() {A m(2,3); cout<<m; cin>>m; } 运行: 2**3 Input:4 5↙ 4**5
# include "iostream.h" # include "iomanip.h" class time {public: time(int i, int j, int k):h(i), m(j), s(k){} friend ostream & operator<<(ostream &,time); friend istream & operator>>(istream &, time &); private: int h, m, s; }; ostream & operator<<(ostream & out, time a) {out<<setfill('0')<<setw(2)<<a.h<<":"<<setfill('0')<<setw(2)<<a.m<< ":"<<setfill('0')<<setw(2)<<a.s<<endl; return out;} istream & operator>>(istream & in, time & b) {in>>b.h>>b.m>>b.s; cout<<'\n'; return in;} void main() {time x(11,22,33),y(2,3,4); cout<<x<<y; cin>>x>>y; } 运行: 11:22:33 02:03:04 8 7 6↙ 12 3 4↙ 08:07:06 12:03:04