1) 与C语言 I/O库<cstdio>函数的比较
l printf (%s%f%d”,…)
即使使用它一个,所有关于I/O的操作库函数都要包含进来,使得程序变大。
l 另外,它是运行时才解析输出格式,效率比较低。
l C I/O缺乏编译时刻检查,比如,里面是%s,传入的参数却是整数。运行时刻才抛出异常。
l C I/O不具备可扩展性,只能输出基本类型的数据,不能重载输出自定义类型的数据。
2) C++ I/O流结构
为了方便,C++定义了<iosfwd>头文件,一般只需include它就行;不行的话再include<iostream>。
l ios_base基类 :public ios
定义了所有流共有的内容,不依赖于流所处理的字符类型。
l basic_ios<charT> :public ios_base
定义跟字符相关的输入输出共有的类,一般很少使用。
l basic_istream<charT> : public basic_ios<charT>
typedef basic_istream<char> istream;
typedef basic_istream<wchar_t> wistream;
istream cin;
l basic_ostream<charT> : public basic_ios<charT>
typedef basic_ostream<char> ostream;
typedef basic_ostream<wchar_t> wostream;
ostream cout;
ostream cerr;
cerr与cout的不同是cerr不带缓冲区(将unitbuf打开),比较快。
l basic_iostream<charT>
: public basic_istream<charT>,
basic_ostream<charT>
typedef basic_iostream<char> iostream;
typedef basic_iostream<wchar_t> wiostream;
3) 重载I/O
l ostream& operator << (ostream& os, const Data& data)
ostream参数不能是const,因为输出会改变流的状态。
l istream& operator >> (istream& is, const Data& data)
istream参数不能是const,因为输入会改变流的状态。
4) 按行输入
l get(缓冲区指针,缓冲区大小,结束符 = ‘/n’) – istream 成员函数
其遇到结束符时,不从流中提取它,然后方法返回。怎么办呢,只能想办法把结束符去掉,然后再进行读取。
怎么去呢?可以换一个结束符,读取一个字符,就去掉了,或者参考下面做法。
所以,一般不用它。
while(cin.get(buf, 1024))
{
cin.get(); //去掉/n
或者
cin.ignore(跳过的字符数 = 1, 遇到字符退出 = EOF(-1)
}
l getline(缓冲区指针,缓冲区大小,结束符 = ‘/n’) – istream成员函数
与get的区别是,其会从流中把结束符去掉,同时,不把它放进缓冲区。
l <string>中的全局getline(istream, string)
比上述getline好的地方在于,string的内存是可扩充的,不用担心缓冲区大小。
l 吸收空格
cin>>ws; //可用于吸收所有空格,ws是内置方法
5) 流状态分类
l ios::badbit 或ios_base::badbit (以下类似) – bad()
致命性错误,流不能继续使用。
只有设置了badbit,bad()才返回true。
l ios::eofbit – eof()
输入结束。
只有当输入结束时,eof()才返回true。
l ios::failbit – fail()
非法数据等IO失败,流可以继续使用,但是,在流恢复到正常状态前,流的所有操作会被忽略。
当输入结束eof()为true或者设置了failbit或badbit, fail()才返回true。
l ios::goodbit - good()
一切正常。
仅当其他为true时,这个才能为true。
l 设置标志 – setstate()
比如,setstate(ios::failbit)
l 清除错误标志 – clear()
- 用clear()还原所有标志位
- 用clear(ios::failbit | ios::badbit) 选择性的清除
6) 流错误处理
l 手动检查流状态 – 一般不用了
istream& operator >> (istream& is, Date& date)
{
is >> date.year;
char dash;
is >> dash;
if( dash != '-' )
{
is.setstate(ios::failbit);
}
//出错了以后就不会处理输入了。
is >> date.month;
is >> dash;
if( dash != '-' )
{
is.setstate(ios::failbit);
}
is >> date.day;
return is;
}
Date myday;
memset(&myday, 0,sizeof(myday));
cin >> myday;
cout<<endl<<myday.year<<" "<<myday.month<<" "<<myday.day<<endl;
cin.clear(); //流恢复
int age = 0;
cin >> age;
如果输入 1981 02 21
则输出是 1981 0 0,因为流出错了,会忽略所有其他流操作。
l 异常处理 – 推荐的处理方式
在任何状态标志设置了都可以抛出异常,一般只在错误状态设置了才抛出异常。
如,cin.exceptions(ios::badbit);
cin.exceptions(ios::failbit);
try
{
Date myday;
cout<<myday.year<<myday.month<<myday.day<<endl;
memset(&myday, 0,sizeof(myday));
cout<<myday.year<<myday.month<<myday.day<<endl;
cin >> myday;
cout<<endl<<myday.year<<" "<<myday.month<<" "<<myday.day<<endl;
}
catch(std::ios_base::failure e)
{
cout<<"输入错误"<<endl;
}
关于异常,请参考
http://blog.csdn.net/yeming81/archive/2010/06/16/5673070.aspx