C++课件第10章:流类库和输入输出
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第10章 流类库和输入输出
东南大学 生物科学与医学工程学院 夏小俊
本章要点
了解输入/输出流类库的相关概念 掌握文本文件和二进制文件读写 掌握提取和插入运算符的重载
10.1 C++的基本流类体系
basic_ ios
指针
basic_ streambuf
basic_ istream
basic_ ostream
cin>>score;
cin.clear(ios::goodbit);
cin.ignore(255 ,'\n');
}while(score<0||score>100);
提高程序健壮性:清空缓冲区
方法三、使用函数cin.sync()清空输入缓冲区 do { cout<<"请输入您的分数:";
cin>>score;
• inline int ios::eof() const {return state&eofbit;}
//返回流(文件)结束位
• inline int ios::fail() const{return
state&(badbit|failbit);}
//返回操作非法和操作失败这两位
• inline int ios::good() const{return state==0;}
提高标准输入/输出的稳健性
• cin为缓冲流。如果输入错了,回车键按下就
无法挽回了。只有把数据取完后,才能重来。
• 输入的数据类型必须与要提取的数据类型一致,
否则出错。出错只是在流的状态字state中对 应位置位,要重来必须重置状态。
但无法分隔字符和字符串。
• 空格、回车和制表符可以用来分隔数值数据,
10.2 文件的输入与输出
• C++根据文件(file)内容的数据格式,可分
为两类:二进制文件和文本文件。
• 文本文件由字符序列组成,也称ASCII码文件,
在文本文件中存取的最小信息单位为字符 (character),而二进制文件中存取的最小 信息单位为字节(Byte)。
率较高。
• 文本文件的读写容易理解,二进制文件读写效
文件。这样在文件流对象和磁盘文件名之间建 立联系。以ifstream类为例:
读写文件的打开方式
打开方式 ios::in ios::out ios::ate ios::app ios::trunc ios::binary 读/写 只读方式 只写方式 定位到尾部 只写追加方式 覆盖方式 二进制必须 说明 文件不存在报错 文件存在覆盖 等待后续操作 文件存在继续写
重载插入和提取运算符
• 插入和提取运算符只能重载为类的友元函数 • 提取运算符重载格式:friend
• 插入运算符重载格式:friend
istream&operator>>(istream&,classNa me&); ostream&operator<<(ostream&,classN ame&);
//格式为d,(d),(d,d)
double re=0,im=0; char c=0; s>>c; if(c=='('){//是否由括号开始
s>>re>>c; //实部
if(c==',') s>>im>>c; //虚部 if(c!=')') s.clear(ios::failbit); }
//漏了括号给一个操作失败标志
• 流对象作为返回值和参数必须是引用!!!
插入运算符重载:mystring类
• 重载插入运算符“<<”声明为mystring的友
元:
friend ostream & operator<<(ostream & ,const mystring &); 定义为: ostream & operator<<(ostream & s,const mystring & cstr) { return s<<cstr.str<<'\t';}
else{ s.putback(c); //无括号,返回一个字符到输入缓冲区 s>>re; } //实数
if(s)a=Complex(re,im);
return s;}
提取运算符重载:复数类
• 分析课本上的这个例子,觉得有什么优点和不
足? 性
• 优点:考虑了多种的实际情况,有一定的健壮 • 缺点:在输入之前没有提示,程序不够友好 • 在实验当中给出自己的修改意见
• 读写文件需包含头文件fstream
读写文件四部曲
• 1、定义文件对象,根据读写方式区分
ifstream ifile;//只输入用 ofstream ofile;//只输出用 fstream iofile;//既输入又输出用
读写文件四部曲
• 2、使用文件流对象的成员函数打开一个磁盘
void ifstream::open(const char*,int =ios::in, int=filebuf::openprot); 其中参数一是字符串形式的文件名,参数二是 打开方式,参数三一般使用默认值。 注意:如果文件名中包含路径,\符号必须连 续使用,如d:\\my.txt
cout<<endl;
}
插入运算符重载:复数类
ostream&operator<<(ostream&s,const Complex &z) { return s<<'('<<z.Real<<','<<z.Image<<')';
}
提取运算符重载:复数类
istream&operator>>(istream&s,Complex &a){
cin.clear(ios::goodbit);
cin.sync();
}while(score<0||score>100);
标准输入/输出成员函数
• int istream::get(); • istream&istream::get(char &); • istream&istream::get(char
cerr<<“SEU”; //更换cout和clog对比
j=5/i;
return 0;
}
cout的重定向(*)
#include <iostream>
using namespace std;
int main() {
cout<<"SEU\n";
cerr<<"NJU\n"; clog<<"PKU\n"; return 0; } //命令行方式下运行 **.exe >>**.txt
• istream&istream::getline(char
*,int,char=’\n’); //不提取终止符
*,int,char=’\n’); //提取终止符并丢弃
提示:如果是超出数量而结束字符串输入,需 要重置流状态。
标准输入/输出成员函数
char s[100];
int num; cin.getline(s,2,‘#’); //如输入abcd# cout<<s<<endl; cin.clear(0);cin.sync(); //必须写这两句 cin>>num; cout<<num<<endl;
basic_ ifstream
basic_ iostream
basic_ ofstream
basic_ fstream
C++的基本流类体系说明(*)
• basic_streambuf不是basic_ios的派生类,而是一个
独立的类,只是basic_ios有一个保护访问限制的指针 指向它,其作用是管理一个流的缓冲区。
• 特别需要注意在输入字符和字符串之前的操作。
程序健壮性的示例:输入成绩
int score; do {
cout<<"请输入您的分数:";
cin>>score;
}while(score<0||score>100);
猜测:如果输入一个字符a,后果是?
提高程序健壮性:掌控流状态
状态字state为整型
enum ios_state{ goodbit=0x00, failbit=0x02, badbit=0x04, } //流正常 //最近的I/O操作失败,流可恢复 //最近的I/O操作非法,流可恢复
state&(badbit|failbit);} //可用操作符!()代替fail()
• inline int ios::bad(){ return state & badbit;}
//返回非法操作位
提高程序健壮性:掌控流状态
• inline void ios::clear(int
_i){ lock();state=_i;unlock();} //人工设置状态,可用来清状态
eofbit=0x01, //输入流结束或文件结束已无数据可取
hardfail=0x08 // I/O出现致命错误,流不可恢复
提高程序健壮性:掌控流状态
读取状态的有关操作如下:
• inline int ios::rdstate() const {return state;}
//读取状态字
• inline int ios:operator!() const{return
//正常返回1,否则返回0
程序健壮性的示例:输入成绩
int score; do { cin.clear(); cout<<"请输入您的分数:"; cin>>score;
}while(score<0||score>100);
猜测:这样的改进有用吗?
提高程序健壮性:清空缓冲区
方法一、用cin.getline()等方式提走缓冲区内容
示器为标准输出设备。
标准输出流对象的区别
对象名 cout clog cerr 是否使用缓冲区 是 是 否 是否可以重定向 是 否 否
注:这里的区别与头文件、编译环境和运行环境 都有较大影响,具体细节非常复杂。
cerr对象的不缓冲特性(*)
#include <iostream.h> //传统头文件 int main() { int i=0,j;
插入运算符重载: Orderedlist类
template <typename T,int size> void <T,size>::print(){ int i; for(i=0;i<=last;i++) { cout<<slist[i].key; //这句是关键 if(i%5==4) cout<<endl;}
• basic_ios类模板提供了对流进行格式化输入输出和错
• *从技术上讲,模板并不能派生。但是这些模板只是预
标准输入/输出流对象
• 在C++的流类库中定义了四个全局流对象:
cin,cout,cerr和clog。
• cin标准输入流对象,键盘为其对应的标准设
备。
• cout、 cerr和clog都是标准输出流对象,显
int=filebuf::openprot);
• fstream::fstream(const char*,int,
int=filebuf::operprot);
读写文件的四部曲
• 打开文件也应该判断是否成功,若成功,文件流对象
值为非零值,不成功为0(NULL)。
• 因此打开一个文件完整的程序为:
do { cout<<"请输入您的分数:"; cin>>score; cin.clear(ios::goodbit); cin.getline(s,100); //char s[100]; }while(score<0||score>100);
提高程序健壮性:清空缓冲区
方法二、使用函数cin.ignore()提取缓冲区内容 do { cout<<"请输入您的分数:";
提取运算符和插入运算符
• 提取运算符“>>”(stream_extraction
operator)和插入运算符“<<” (stream_insertion operator),执行输入 /输出操作。 “提取”的含义是指输入操作,可看作从流中 提取一个字符序列。
•
•
“插入”的含义是指输出操ቤተ መጻሕፍቲ ባይዱ,可看作向流中 插入一个字符序列。
读写文件的四部曲
• 三个文件流类都重载了一个带默认参数的构造函数,
功能与open函数一样:
• ifstream::ifstream(const char*, int=ios::in,
int=filebuf::openprot);
• ofstream::ofstream(const char*,int=ios::out,
误处理的成员函数。basic_istream类模板提供完成提 取(输入)操作的成员函数,basic_ostream类模板 提供完成插入(输出)操作的成员函数。 basic_iostream类是前两者的聚合,并没有增加成员。 先定义了数据类型(如char或wchar_t等等)的模板实 例,所以可以继承。
东南大学 生物科学与医学工程学院 夏小俊
本章要点
了解输入/输出流类库的相关概念 掌握文本文件和二进制文件读写 掌握提取和插入运算符的重载
10.1 C++的基本流类体系
basic_ ios
指针
basic_ streambuf
basic_ istream
basic_ ostream
cin>>score;
cin.clear(ios::goodbit);
cin.ignore(255 ,'\n');
}while(score<0||score>100);
提高程序健壮性:清空缓冲区
方法三、使用函数cin.sync()清空输入缓冲区 do { cout<<"请输入您的分数:";
cin>>score;
• inline int ios::eof() const {return state&eofbit;}
//返回流(文件)结束位
• inline int ios::fail() const{return
state&(badbit|failbit);}
//返回操作非法和操作失败这两位
• inline int ios::good() const{return state==0;}
提高标准输入/输出的稳健性
• cin为缓冲流。如果输入错了,回车键按下就
无法挽回了。只有把数据取完后,才能重来。
• 输入的数据类型必须与要提取的数据类型一致,
否则出错。出错只是在流的状态字state中对 应位置位,要重来必须重置状态。
但无法分隔字符和字符串。
• 空格、回车和制表符可以用来分隔数值数据,
10.2 文件的输入与输出
• C++根据文件(file)内容的数据格式,可分
为两类:二进制文件和文本文件。
• 文本文件由字符序列组成,也称ASCII码文件,
在文本文件中存取的最小信息单位为字符 (character),而二进制文件中存取的最小 信息单位为字节(Byte)。
率较高。
• 文本文件的读写容易理解,二进制文件读写效
文件。这样在文件流对象和磁盘文件名之间建 立联系。以ifstream类为例:
读写文件的打开方式
打开方式 ios::in ios::out ios::ate ios::app ios::trunc ios::binary 读/写 只读方式 只写方式 定位到尾部 只写追加方式 覆盖方式 二进制必须 说明 文件不存在报错 文件存在覆盖 等待后续操作 文件存在继续写
重载插入和提取运算符
• 插入和提取运算符只能重载为类的友元函数 • 提取运算符重载格式:friend
• 插入运算符重载格式:friend
istream&operator>>(istream&,classNa me&); ostream&operator<<(ostream&,classN ame&);
//格式为d,(d),(d,d)
double re=0,im=0; char c=0; s>>c; if(c=='('){//是否由括号开始
s>>re>>c; //实部
if(c==',') s>>im>>c; //虚部 if(c!=')') s.clear(ios::failbit); }
//漏了括号给一个操作失败标志
• 流对象作为返回值和参数必须是引用!!!
插入运算符重载:mystring类
• 重载插入运算符“<<”声明为mystring的友
元:
friend ostream & operator<<(ostream & ,const mystring &); 定义为: ostream & operator<<(ostream & s,const mystring & cstr) { return s<<cstr.str<<'\t';}
else{ s.putback(c); //无括号,返回一个字符到输入缓冲区 s>>re; } //实数
if(s)a=Complex(re,im);
return s;}
提取运算符重载:复数类
• 分析课本上的这个例子,觉得有什么优点和不
足? 性
• 优点:考虑了多种的实际情况,有一定的健壮 • 缺点:在输入之前没有提示,程序不够友好 • 在实验当中给出自己的修改意见
• 读写文件需包含头文件fstream
读写文件四部曲
• 1、定义文件对象,根据读写方式区分
ifstream ifile;//只输入用 ofstream ofile;//只输出用 fstream iofile;//既输入又输出用
读写文件四部曲
• 2、使用文件流对象的成员函数打开一个磁盘
void ifstream::open(const char*,int =ios::in, int=filebuf::openprot); 其中参数一是字符串形式的文件名,参数二是 打开方式,参数三一般使用默认值。 注意:如果文件名中包含路径,\符号必须连 续使用,如d:\\my.txt
cout<<endl;
}
插入运算符重载:复数类
ostream&operator<<(ostream&s,const Complex &z) { return s<<'('<<z.Real<<','<<z.Image<<')';
}
提取运算符重载:复数类
istream&operator>>(istream&s,Complex &a){
cin.clear(ios::goodbit);
cin.sync();
}while(score<0||score>100);
标准输入/输出成员函数
• int istream::get(); • istream&istream::get(char &); • istream&istream::get(char
cerr<<“SEU”; //更换cout和clog对比
j=5/i;
return 0;
}
cout的重定向(*)
#include <iostream>
using namespace std;
int main() {
cout<<"SEU\n";
cerr<<"NJU\n"; clog<<"PKU\n"; return 0; } //命令行方式下运行 **.exe >>**.txt
• istream&istream::getline(char
*,int,char=’\n’); //不提取终止符
*,int,char=’\n’); //提取终止符并丢弃
提示:如果是超出数量而结束字符串输入,需 要重置流状态。
标准输入/输出成员函数
char s[100];
int num; cin.getline(s,2,‘#’); //如输入abcd# cout<<s<<endl; cin.clear(0);cin.sync(); //必须写这两句 cin>>num; cout<<num<<endl;
basic_ ifstream
basic_ iostream
basic_ ofstream
basic_ fstream
C++的基本流类体系说明(*)
• basic_streambuf不是basic_ios的派生类,而是一个
独立的类,只是basic_ios有一个保护访问限制的指针 指向它,其作用是管理一个流的缓冲区。
• 特别需要注意在输入字符和字符串之前的操作。
程序健壮性的示例:输入成绩
int score; do {
cout<<"请输入您的分数:";
cin>>score;
}while(score<0||score>100);
猜测:如果输入一个字符a,后果是?
提高程序健壮性:掌控流状态
状态字state为整型
enum ios_state{ goodbit=0x00, failbit=0x02, badbit=0x04, } //流正常 //最近的I/O操作失败,流可恢复 //最近的I/O操作非法,流可恢复
state&(badbit|failbit);} //可用操作符!()代替fail()
• inline int ios::bad(){ return state & badbit;}
//返回非法操作位
提高程序健壮性:掌控流状态
• inline void ios::clear(int
_i){ lock();state=_i;unlock();} //人工设置状态,可用来清状态
eofbit=0x01, //输入流结束或文件结束已无数据可取
hardfail=0x08 // I/O出现致命错误,流不可恢复
提高程序健壮性:掌控流状态
读取状态的有关操作如下:
• inline int ios::rdstate() const {return state;}
//读取状态字
• inline int ios:operator!() const{return
//正常返回1,否则返回0
程序健壮性的示例:输入成绩
int score; do { cin.clear(); cout<<"请输入您的分数:"; cin>>score;
}while(score<0||score>100);
猜测:这样的改进有用吗?
提高程序健壮性:清空缓冲区
方法一、用cin.getline()等方式提走缓冲区内容
示器为标准输出设备。
标准输出流对象的区别
对象名 cout clog cerr 是否使用缓冲区 是 是 否 是否可以重定向 是 否 否
注:这里的区别与头文件、编译环境和运行环境 都有较大影响,具体细节非常复杂。
cerr对象的不缓冲特性(*)
#include <iostream.h> //传统头文件 int main() { int i=0,j;
插入运算符重载: Orderedlist类
template <typename T,int size> void <T,size>::print(){ int i; for(i=0;i<=last;i++) { cout<<slist[i].key; //这句是关键 if(i%5==4) cout<<endl;}
• basic_ios类模板提供了对流进行格式化输入输出和错
• *从技术上讲,模板并不能派生。但是这些模板只是预
标准输入/输出流对象
• 在C++的流类库中定义了四个全局流对象:
cin,cout,cerr和clog。
• cin标准输入流对象,键盘为其对应的标准设
备。
• cout、 cerr和clog都是标准输出流对象,显
int=filebuf::openprot);
• fstream::fstream(const char*,int,
int=filebuf::operprot);
读写文件的四部曲
• 打开文件也应该判断是否成功,若成功,文件流对象
值为非零值,不成功为0(NULL)。
• 因此打开一个文件完整的程序为:
do { cout<<"请输入您的分数:"; cin>>score; cin.clear(ios::goodbit); cin.getline(s,100); //char s[100]; }while(score<0||score>100);
提高程序健壮性:清空缓冲区
方法二、使用函数cin.ignore()提取缓冲区内容 do { cout<<"请输入您的分数:";
提取运算符和插入运算符
• 提取运算符“>>”(stream_extraction
operator)和插入运算符“<<” (stream_insertion operator),执行输入 /输出操作。 “提取”的含义是指输入操作,可看作从流中 提取一个字符序列。
•
•
“插入”的含义是指输出操ቤተ መጻሕፍቲ ባይዱ,可看作向流中 插入一个字符序列。
读写文件的四部曲
• 三个文件流类都重载了一个带默认参数的构造函数,
功能与open函数一样:
• ifstream::ifstream(const char*, int=ios::in,
int=filebuf::openprot);
• ofstream::ofstream(const char*,int=ios::out,
误处理的成员函数。basic_istream类模板提供完成提 取(输入)操作的成员函数,basic_ostream类模板 提供完成插入(输出)操作的成员函数。 basic_iostream类是前两者的聚合,并没有增加成员。 先定义了数据类型(如char或wchar_t等等)的模板实 例,所以可以继承。