参考资源:( http://www.cnblogs.com/kingcat/archive/2012/05/09/2491847.html )
C++ 的输入/输出由标准库提供。
标准库IO 的继承,使类有相同的接口,但是也是错误发生的根源。(一些错误可恢复;一些错误则发生在系统底层,而在程序修正范围之外)
iostream 为内置类型对象提供了输入输出支持,类的设计者也可以通过运算符重载机制扩充 iostream 库,使其支持自定义类型的输入输出操作。
1.OO之标准库
简单的 iostream 继承图:
*函数有基类类型的引用形参时,可以给函数传递其派生类型的对象。三种类型流:控制台、磁盘文件和字符串流(对内存读写)。
支持国际字符(wchar_t):头文件相同,所有类都加上 "w" 前缀。
IO 对象不能复制、赋值:
1.不支持复制------->不能存储在 vector(或其他)容器
2.形参、返回类型不能为流类型。对 IO 对象读写会改变它的状态,故引用必须是 非const 的。
2.条件状态(condition state)
/********* 流状态查询、控制 **********/
#include <iostream>
using namespace std;
int main()
{
int ival;
while (cin >> ival, !cin.eof())
{
if (cin.bad()) // input stream is corrupted; bail out
throw runtime_error("IO stream corrupted");
if (cin.fail()) { // bad input
cerr<< "bad data, try again"; // warn the user
cin.clear(istream::goodbit); // reset the stream
cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n'); // ignore bad input
continue; // get next input
}
else
{
cout << cin << endl;
break;
}
// ok to process ival
}
return 0;
}
/******* 条件状态下的访问 *********/
istream::iostate old_state=cin.rdstate();
cin.clear();
process_input(); // use cin
cin.clear(old_state); // now reset cin to old state
多种状态的处理:is.setstate( ifstream::badbit | ifstream::failbit | ... ); 与二进制位按位或处理。
3.输出缓冲区的管理
缓冲区被刷新:
1.程序正常结速时,将清空所有输出缓冲区。
2.在一些不确定的时候,缓冲区可能已经满了,这种情况下,缓冲区将会在写入下一个值之前刷新缓冲区。
cout<<"Hi!"<<endl; //插入换行符,并刷新缓冲区
cout<<"Hi!"<<ends; //插入空格字符null,并刷新缓冲区
cout<<"Hi!"<<flush; //仅仅刷新缓冲区,不插入任何其他字符
3.用操纵符(endl, ends,flush)显式地刷新缓冲区:
4.用unitbuf操纵符设置流的内部状态,则流在每次输出操作执行完都清空缓冲区,恢复系统管理缓冲区刷新方式方式用nounitbuf。
cout<<unitbuf<<"first"<<"second"<<"third"<<nounitbuf;
等价于:
cout<<"first"<<flush<<"second"<<flush<<"third"<<flush;
5.使用tie函数将输出流与输入流关联起来,当输入流与输出流绑定在一起的时候,任何输入操作都将首先刷新其输出流关联的缓冲区。( 此处不太懂:内容来自 primer )
tie 函数可用 istream 或 ostream 对象调用,使用一个指向 ostream 对象的指针形参。调用 tie 函数时,将实参流绑在调用该函数的对象上。如果一个流调用 tie 函数将其本身绑在传递给 tie 的 ostream 实参对象上,则该流上的任何 IO 操作都会刷新实参所关联的缓冲区。
cin.tie(&cout); // illustration only: the library ties cin and cout for us
ostream *old_tie = cin.tie();
cin.tie(0); // break tie to cout, cout no longer flushed when cin is read
cin.tie(&cerr); // ties cin and cerr, not necessarily a good idea!
// ...
cin.tie(0); // break tie between cin and cerr
cin.tie(old_tie); // restablish normal tie between cin and cout
一个 ostream 对象每次只能与一个 istream 对象绑在一起。如果在调用 tie 函数时传递实参 0,则打破该流上已存在的捆绑。
#include<fstream>
#include<iostream>
using namespace std;
int main()
{
ofstream outfile("C:\\Users\\liyangguang\\text.txt");
cin.tie(&outfile); //若注释,则直到文件流结束才写入文件
outfile<<"A ordinary day!";
int i;
cin>>i;
// system("pause");
outfile.close();
// system("pause");
return 0;
}
4.文件的输入和输出
定义自己的文件流对象:绑定在文件上。
fstream 还定义自己的两个新操作:open 和 close, 以及形参为要打开文件名的构造函数。
流初始化1.
void open(const char *filename, openmode mode);
void close(); // 关闭流并不能改变流对象的内部状态。
cout ,cin 分别是 istream,ostream 类的对象。
因为 cout, cin 指向的是标准设备(显示器屏幕,键盘),所以它在 iostream 头文件中作为全局对象进行定义。但是文件设备不是标准默认设备,所以它在 fstream 头文件中是没有预先定义的全局对象,我们必须自己定义一个对象。例如:要以文件作为设备向文件输出信息,那么就应该使用 ofstream 类。
ofstream类的默认构造函数原形为:
流初始化2.
ofstream::ofstream(const char *filename,int mode = ofstream::out(ios::out),int openprot = filebuf::openprot);
filename: 文件名mode: 打开的文件模式
prot: 打开文件的属性
其中 mode 和 openprot 这两个参数的可选项表见下表:
mode属性表( 模式是文件的属性 )
in 打开文件做读操作
out 打开文件做写操作
app 在每次写之前找到文件尾( append )
ate 打开文件后立即将文件定位在文件尾
trunc 打开文件时清空已存在的文件流( 如果文件存在,把文件长度设为0 )
binary 以二进制模式进行 IO 操作
可以用或把以上属性连接起来.
openprot属性表:
0:普通文件,打开访问
1:只读文件
2:隐含文件
4:系统文件
文件模式组合:
ofstream file("example.bin", ofstream::out | ofstream::app | ofstream::binary);
// 等价于
ofstream file ;
file.open("example.bin",ofstream::out | ofstream::app | ofstream::binary) ;
5.字符串流stringstream 对象的使用:
#include<sstream>
#include<iostream>
using namespace std;
int main()
{
string line,word;
while(getline(cin,line))
{
istringstream stream(line); // bind to stream to the line we read
cout<<line<<endl;
while(stream>>word) // read a word from line
cout<<word<<endl;
}
}
转换\格式化:
#include<sstream>
#include<iostream>
using namespace std;
int main()
{
int val1=512,val2=1024;
ostringstream format_message;
format_message<<"val1 = "<<val1<<"\n"
<<"val2 = "<<val2<<"\n";
string s=format_message.str();
cout<<s;
istringstream input_istring(format_message.str());
string s2;
input_istring>>s2>>val1>>s2>>val2;
cout<<val1<<" "<<val2<<endl;
cout<<s2<<endl;
return 0;
}