本章内容太多,分多次写完。这里存在的一个争议就是,是选择标准stream还是传统的C输入输出函数?
就性能而言,毫无疑问C函数要高,但是普通的测试下,stream和C函数的性能差距没达到10倍以上,因此普通应用场景下两者并没有区别。
stream优势在于使用模板编写,数据通用性强,尤其是可以解决国际化问题。
操作便利程度而言,两者各有千秋。
总的来说做应用用stream,做底层和高性能用C函数。Google编码规范建议主要用C的输入输出函数。
(一)基本概念
1、全局通用函数有
a) cin标准输入通道,对应于stdin。宽字符为wcin
b) cout标准输出通道,对应于stdout宽字符为wcout
c) cerr。标准错误输出通道。对应于stderr。其实现目标之一是,将信息输入文件,同时把错误信息输出到控制台。宽字符为wcerr
d) clog。标准logging通道。宽字符为wclog
注意:连续读入两个数据:
cin >> x >> y;
但是如果这样做,就出错:
cin >>x;
cin>>y;
y的值变成了回车。
正确做法是清理缓冲区:
cin >>x;
cin.clear();
cin.sync();//清空剩余缓冲区
cin >> y;
C函数有时候也面临同样的问题:
scanf(“%d”, &x);
scanf(“%d”, &y);
y等于回车。
正确做法:
scanf(“%d”, &x);
fflush(stdin);//清空输入缓冲区
scanf(“%d”, &y);
2、操控器专门操控stream对象,一般改变格式化解释方式。
操控器 |
作用 |
endl |
输出’\n’,然后刷新输出缓冲区 |
ends |
输出’\0’ |
flush |
刷新输出缓冲区 |
ws |
读入并忽略空格 |
(二)基本stream类别
1、基类ios_base定义了状态和标志位
2、basic_ios继承ios_base,这里主要是type_traits
3、basic_istream和basic_ostream虚拟继承basic_ios,主要是避免ios_base的重复继承。定义了读\写对象。
4、basic_iostream多重继承了basic_istream和basic_ostream,定义了可读可写对象。
5、basic_sreambuf是iostream库的核心,基本所有的读写接口在这里定义。是实际进行字符读写操作的代码。
6、stream buffer class的用途。iostream严格按照“职责分离”原则编写。basic_ios只定义了对象和操作格式,其实关键的都没有。basic_ios负责调用和维护stream buffer。stream buffer提供了缓冲区,同时提供了实际的读写操作。
7、特殊IO
类别 |
说明 |
bool |
真就是1,假就是0,其他会报错 |
char* |
用以下方法设置字符串最大80个字符: char buffer[81]; cin>>setw(81)>>buffer |
void* |
打印地址 |
(三)状态
1、iostate常数反映stream状态。不过这个东西很多人都很头疼。调用的时候得加上作用域:std::ios_base::eofbit或者std::ios::eofbit。
常量 |
意义 |
goodbit |
完全正常 |
eofbit |
遇到末尾标记 |
failbit |
错误 |
badbit |
不确定的毁灭性的错误,必须得停止 |
2、eofbit和failbit经常一起出现。
3、关于状态的成员函数
成员函数 |
意义 |
good() |
正常返回true |
eof() |
遇到末尾标记,返回true |
fail() |
发生错误,返回true |
bad() |
毁灭性的错误,返回true |
rdstate() |
返回当前已经设立的所有标志 |
clear() |
清除所有标志 |
clear(state) |
清除标志,在设立state标志 |
setstate(state) |
加设state标志 |
比如只清除failbit标志位:
strm.clear(strm.rdstate()& !std::ios::failbit);
如果发生错误,必须手动清除错误标志位后,才能继续下一步操作。
4、布尔表达式转化
成员函数 |
意义 |
operator void * |
stream没出错 |
operator ! () |
stream出错 |
注意这两个重载函数返回bool型,而不是stream类。例子:
while(std::cin){
....}
while(std::cin >>x){
...}
while(!std::cin){
....}
while(!(std::cin>> x)){
...}//注意要打括号!
(四)异常
成员函数 |
意义 |
exceptions(flags) |
设定会引发异常的标志 |
exception |
返回引发异常的标志 |
对所有标志抛出异常:
strm.exceptions(std::ios::eofbit |std::ios::failbit | std::ios::badbit);
但是传入0和goodbit是不会引发异常。
抛出的异常是std::ios_base::failure对象,继承自exception,是个标准的异常安全类,用法也一样。
例子:
try{
输入输出操作。。。
}
catch(const ios::failure& err){
cerr << “,IOexception : ” << err.what() << endl;
returnEXIT_FAILURE;
}
catch(const exception& err){
cerr << “,Standardexception : ” << err.what() << endl;
returnEXIT_FAILURE;
}
catch(...){
cerr << “unknownerror” << endl;
returnEXIT_FAILURE;
}