C++的I/O(vc版)(七)

  首先,我们还有很多的类没有分析:istream,filestream,filebuf,还有对应得迭代器。第二,即使前面的分析也不能说明I/O的使用规范。如果想要熟练的使用I/O,建议读《C++标准程序库》,那是一本经典。第三,流的格式化读取和输出大部分依靠的是locale,而我们前面很少涉及,现在还看不懂源码,只能以后分析了。

 下面摘抄《c++标准程序库》中关于如何自定义I/O操作符的说明。

  一,对于格式化化读取或者输入。

  什么是格式化操作,就是有格式。例如一个文件里都是float,我们就可以按float读取。因为格式化操作都是转交给locale对象的,而根据流中预定义的操作,我们使用operator<<和operator>>来完成格式化处理。所以这里的主题是:如何重载这两个操作符?

  (1)这里完全抄袭《c++标准程序库》中的例子:对于分数Fraction对象,按“分子/分母”格式,进行格式化输入和输出。

inline std::ostream& operator<<(ostream& strm,const Fraction& f)
{
	strm<<f.numerator()<<'/'<<f.denominator();
	return strm;
}

这是大多数人的重载方式,但是有两个缺点:

1.只适用于ostream即:字符型别为char的stream。

2.如果字符宽度被设定,则只会施加于分子上。

改进的重载模式:

template<class charT,class traits>
inline std::basic_ostream<charT,traits>&
	operator<<(std::basic_ostream<charT,traits>& strm,const Fraction& f)
{
	basic_ostringstream<charT,traits> s;
	s.copyfmt(strm);
	s.width(0);//令s的宽度为0,这样对于这个f,就没有填充宽度
	s<<f.numerator()<<'/'<<f.denominator();
	strm<<s.str();
	return strm;
}

(2)同理对于重载:operator>>,我们需要的是检查是否正确:

template<class charT,class traits>
inline std::basic_ostream<charT,traits>&
	operator>>(std::basic_ostream<charT,traits>& strm, Fraction& f)
{
	int n,d;
	strm>>n;
	//检查后面是否是'/'
	if(strm.peek()=='/'){
		strm.ignore();
		strm>>d;
	}else{
		d=1;
	}
	//检查分母是否为0
	if(d==0){
		strm.setstate(ios::failbit);
		return strm;
	}
	//只有上述条件都符合,才能构建fraction'对象
	if(strm){
		f=Fraction(n.d);
	}
	return strm;
}
(3),对于具有虚拟继承和多态特性的输入输出,我们必须借助于辅助函数,然后在<<和>>中调用辅助函数;


二,以非格式化函数完成输入输出

 非格式化就是我们只能一个一个字符的读取,不能直接读取int或者float:

对于这类函数,我们应该直接使用缓冲类的接口,因为这样就没有sentry的代价,否则,每调用一次<<或>>就会产生一个sentry。

流中有很多预定义的非格式化输入输出函数:如write,read。。。

三:直接使用stream缓冲区:

  进行无格式化I/O时,我们尽量使用缓冲区操作,对于缓冲区的操作接口,这里不列出。

 主要说明的是我们前面文章提到的_Myt&   operator<<(_Mysb *_Strbuf)操作符:

cout<<cin.rdbuf();
cin>>noskipws>>cout.rdbuf();

由源码我们得知:会将缓冲区的内容全部输入和输出,同时缓冲区的指针也移动到末尾。

对于格式化的I/O,我们有时候出于效率的考虑,也会直接使用缓冲区,因为格式化的工作交给了locale,我们必须自己使用locale对象操作,这样的话就不必总是构造sentry对象;但是----不安全!


四,自定义I/O操作符的惯例:

(1)你的输出格式应该能让其他的使用者使用input操作符无损的读取数据,尤其是strings的空格问题;

(2)进行I/O时,应该考虑现有的stream格式规范,尤其是改写宽度时;

(3)如果发生错误,应设立相应的状态位;

(4)如果发生错误,原对象不应有任何改变。如果读取多个数据,读入的数据应该在被传递到对象前,先存储于辅助对象;

(5)输出不应以new line符号结束

(6)如果检测到某个格式错误,应该尽可能的不读取任何字符。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值