S08IO库
一、IO类
1、IO库类型和头文件
iostream //istream/ostream/iostream,读写流,若前缀w如wistream表示对宽字符的支持
fstream //ifstream/ofstream/fstream,读写文件,若前缀w表示对宽字符的支持
sstream //istringstream/ostringstream,读写string,若前缀w表示对宽字符的支持
(1)由于fstream和sstream定义的文件流类型和string流类型都是继承自iostream定义的流类型,因此可以像使用cin/cout等对象一样来使用文件和string流类型的对象(例如函数形参是ostream&,实参可以是ofstream)
(2)IO对象没有拷贝或赋值
(3)基本操作
ofstream out1, out2;
out1 = out2; //错误,不能赋值流对象
ofstream print(ofstream); //错误,不能初始化ofstream参数
out2 = print(out2); //错误,不能拷贝流对象
2、进行IO操作的函数通常以引用的形式传递和返回流,并且不能是const的
3、IO库的条件状态
strm::iostate //strm是一种IO类型,具体参考1中的内容,iostate提供了表达条件状态的完整功能
strm::badbit //badbit置1表示流已崩溃,系统级错误,无法恢复,该流无法再使用,检测流状态的条件会失败
strm::failbit //failbit置1表示一个IO操作失败,可恢复,检测流状态的条件会失败
strm::eofbit //eofbit置1表示流到达了文件结束,检测流状态的条件会失败
strm::goodbit //goodbit置0表示流未发生错误,只有在goodbit置0时流对象作为条件判断才会为真
s.eof() //若eofbit置1,则返回true
s.fail() //若failbit或badbit置1,则返回true
s.bad() //若badbit置1,则返回true
s.good() //若流有效,则返回true
s.clear(flags) //flags参数可选,类型是strm::iostate,若有则所有状态位置成flags,若无则复位,返回void
s.setstate(flags) //将flags提供的位设置为flags,与clear不同
//clear对每个状态都复位或设置,setstate相当于clear(原状态 | 新状态),返回void
s.rdstate() //返回流的当前条件状态,返回类型为strm::iostate
clear(rdstate() | state) = setstate(state) //clear()与setstate()的关系
4、一旦流出现错误后,后续IO操作都会失败,只有当流不处于错误状态时才能进行正常操作,故使用一个流之前应该检查它的状态
while(cin >> word) {...} //流状态正常时作为条件会返回为真,故可以正常操作
cin.clear(cin.rdstate() & ~cin.failbit & ~cin.badbit); //将fallbit和badbit复位,保持eofbit不变
5、管理输出缓冲,导致缓冲区立即刷新的原因
(1)程序正常结束,main函数return时刷新缓冲区
(2)缓冲区满
(3)
cout << endl
来显式刷新缓冲区并输出换行,
cout << ends
显式刷新缓冲区并输出空格,
cout << flush
显式刷新缓冲区并不附加任何字符
(4)
cout << unitbuf
设置所有输出都立即刷新,无缓冲;
cout << nounitbuf
取消立即刷新
(5)当一个输出流被关联到另一个流时,读写被关联的流时,关联流的缓冲区被刷新
注意:如果程序崩溃,输出缓冲区不会被刷新,可能在缓冲区中会存有已经被程序执行完毕但还未输出的数据
6、tie函数关联输入和输出流,此时参考5(5),缓冲区将会刷新
ostream* tie() const; //返回指向绑定的输出流的指针,若未绑定返回空指针
ostream* tie(ostream* tiestr); //将tiestr指向的输出流绑定的该对象上,并返回上一个绑定的输出流指针
cin.tie(&cout); //将cin关联到cout
ostream *old_tie = cin.tie(nullptr); //cin不再与其他流关联,并使old_tie指向cin上一个绑定的输出流
cin.tie(&cerr); //将cin再关联到cerr上,此时读取cin会刷新cerr
二、文件输入输出
1、fstream特有的操作
fstream fstrm; //创建未绑定的文件流fstrm,fstream是头文件fstream中定义的类型
fstream fstrm(s, mode); //创建一个fstream并打开名为s的文件,s可以是string或C风格的字符串,可选打开模式mode
fstrm.open(s); //打开名为s的文件并与fstrm绑定,返回void
fstrm.close(); //关闭fstrm绑定的文件,返回会void
fstrm.is_open(); //判断fstrm绑定的文件是否成功打开且尚未关闭,返回bool
注意:继承机制保证在要求使用基类型对象的地方(如要求是istream&),可以用继承类型的对象替代(传入ifstream)
2、成员函数
open
和
close
当定义空文件流对象时可以用
open
将它与特定文件关联起来,若在定义时提供了文件名则会自动调用
open
,若
open
调用失败则会将流的
failbit
置1,若要关联另一个文件则首先要调用
close
关闭当前关联的文件,不
close
直接
open
新文件会出错
注意:当一个fstream对象被销毁时,close会被自动调用
3、文件模式,部分限制情况参考《C++primer 5th》p.286
in //读
out //写
app //附加,即写操作前先定位到文件末尾
ate //打开文件立即定位到文件末尾
trunc //截断文件,即清空原有内容
binary //二进制方式IO
ofstream out("file1"); //默认写、截断
ofstream out2("file1", ofstream::out); //默认截断
ofstream out3("file1", ofstream::out | ofstream::trunc); //写,截断,与前两者等价
三、string流
1、sstream特有的操作
sstream strm; //创建未绑定的stringstream对象strm,sstream是头文件sstream中定义的类型
sstream strm(s); //创建一个sstream并保存string s的拷贝
strm.str(); //返回strm保存的s的拷贝
strm.str(s); //将string s保存到strm中,返回void
ostringstream msg;
msg << "C++ Primer the fifth edition" << endl;
istringstream in(msg.str());
四、其他
1、一些课本上的习题或一些参考代码
练习:
//略去头文件等一些细节
istream &func(istream &is)
{
int s1;
while (is >> s1, !is.eof())
{
if (is.bad())
{
throw runtime_error("IOStream Error");
}
else if (is.fail())
{
cerr << "Failed, please try again" << endl;
is.clear();
is.ignore(buffer, '\n'); //buffer = 100
continue;
}
cout << s1 << endl;
}
return is;
}
int main()
{
func(cin);
return ;
}
练习:
//略去头文件等一些细节
int main(int argc, char *argv[])
{
ifstream file;
vector<string> lines;
string line;
if (argc != )
{
cerr << "Wrong argument(s)" << endl;
}
file.open(argv[]);
if (!file)
{
cerr << "Can't open file " << argv[] << endl;
}
while (getline(file, line))
{
lines.push_back(line);
}
file.close();
auto beg = lines.begin(), end = lines.end();
while (beg != end)
{
istringstream words(*beg);
string word;
while (words >> word)
{
cout << word << " ";
}
cout << endl;
++beg;
}
return ;
}
2、iostream类型的设计与scanf/printf的设计有诸多不同,可以参考陈硕的《C++ 工程实践(7):iostream 的用途与局限》来进一步了解iostream