一个关于使用boost::lexical_cast产生异常的问题,关键代码如下
string str(8,'\0');
strncpy(&str.at(0),"1234567",7);
cout << lexical_cast<int>(str) << endl;
结果运行的时候发生如下异常
terminate called after throwing an instance of 'boost::bad_lexical_cast'
what(): bad lexical cast: source type value could not be interpreted as target
我们知道boost::lexical_cast最终使用的stringstream实现的数值类型转换,所以,我们使用如下例子,做测试
stringstream ss;
ss << str;
ss >> result;
cout << "new Result: " << result << endl;
编译运行后,输出
new Result: 1234567
可以正常显示,好像没有问题,
我们察看一下boost的源代码
vim /usr/include/boost/lexical_cast.hpp
察看lexical_cast函数
template<typename Target, typename Source>
Target lexical_cast(Source arg)
{
detail::lexical_stream<Target, Source> interpreter;
Target result;
if(!(interpreter << arg && interpreter >> result))
throw_exception(bad_lexical_cast(typeid(Target), typeid(Source)));
return result;
}
可见lexical_cast函数非常简单,就是具体执行operator<<和operator>>两个操作,只要这两个操作有一个失败就抛出一个异常,为了确认是那步出的错,我们在程序中手工执行这两个操作。代码如下
detail::lexical_stream<int, string> interpreter;
int result;
if(!(interpreter << str ))
{
cout << "Error 1" << endl;
}
if(!(interpreter >> result))
{
cout << "Error 2" << endl;
}
cout << result << endl;
编译运行后输出
Error 2
从这里我们知道,lexical_cast是在执行输出流的时候发生的问题,察看detail的operator>>函数,青年人网提示其源代码如下
template<typename InputStreamable>
bool operator>>(InputStreamable &output)
{
return !is_pointer<InputStreamable>::value &&
stream >> output &&
(stream >> std::ws).eof();
}
根据以上代码和我们使用stringstream做的测试,基本上可以确定在stream>>output(包括次步)都是正确的,可能出现问题的是(stream >> std::ws).eof();
这里解释下std::ws和stringstring::eof()函数
Std::ws函数声明在
/usr/include/c++/3.4.4/bits/istream.tcc
源代码如下
// 27.6.1.4 Standard basic_istream manipulators
template<typename _CharT, typename _Traits>
basic_istream<_CharT,_Traits>&
ws(basic_istream<_CharT,_Traits>& __in)
{
typedef basic_istream<_CharT, _Traits> __istream_type;
typedef typename __istream_type::__streambuf_type __streambuf_type;
typedef typename __istream_type::__ctype_type __ctype_type;
typedef typename __istream_type::int_type __int_type;
const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
const __int_type __eof = _Traits::eof();
__streambuf_type* __sb = __in.rdbuf();
__int_type __c = __sb->sgetc();
while (!_Traits::eq_int_type(__c, __eof)
&& __ct.is(ctype_base::space, _Traits::to_char_type(__c)))
__c = __sb->snextc();
if (_Traits::eq_int_type(__c, __eof))
__in.setstate(ios_base::eofbit);
return __in;
}
主要作用是过滤输入流中的空格,\n\r等字符。stream >> std::ws目的就是把输入流中转换完整形后的剩余流内容(假如有的话)写入std::ws,当然只能写入其中的空格和\n\r等字符。
stringstring::eof()函数参考 http://www.cppreference.com/wiki/io/eof 部分
该函数的主要作用是,如果到达流的结束位置返回true,否则返回false
根据以上信息,我们编写测试用例
stringstream ss;
ss << str;
ss >> result;
cout << "new Result: " << result << endl;
cout << ss.eof() << endl;
cout << (ss >> std::ws).eof() << endl;
责任编辑:小草