【转载】boost的lexical_cast --数据类型转换

注: 转载请保证文章完整性

一、介绍


lexical_cast是boost中一个非常有用,常用,好用的库,我现在的小数据转换用的都是lexical_cast。
lexical_cast最大的特点是安全,包括长度安全,类型安全。
下面我来介绍下lexical_cast的基本使用方法。

Target lexical_cast(Source arg)

例如 
#include <boost/lexical_cast.hpp>           //lexical_cast的头文件
using namespace std;                        //stl的域
using namespace boost;                      //boost的域
int main()
    {
    const double PI=3.1415926535;
    string str;
    str=lexical_cast<string>(PI);
    cout<<str; 
    return 0;
    }

非常容易吧,简单也是他的优势之一。


二、异常


lexical_cast在执行失败时会抛出异常bad_lexical_cast
上面的例子改为
#include <boost/lexical_cast.hpp>           //lexical_cast的头文件
using namespace std;                        //stl的域
using namespace boost;                      //boost的域
int main()
    {
    try
        {
        string str="3.1415926535";
        double PI=lexical_cast<double>(str);
        cout<<PI; 
        return 0;
        }
    catch(bad_lexical_cast& E)
        {
        cout<<E.what()<<endl;
        }
    }

当str为ABCD时,
无法转成PI抛出异常
输出
bad lexical cast: source type value could not be interpreted as target



三、一个小例子


为了加深大加理解
下面使用lexical_cast实现一个简单的文本输入是否为指定类型的小程序

#include <boost/lexical_cast.hpp>
#include <iostream>
using namespace std;                        //stl的域
using namespace boost;                      //boost的域
template<typename _T,typename _R>
bool isElement(_R r)
    {
    try
        {
        lexical_cast<_T>(r);                
        return true;                        //转换成功
        }
    catch(...)
        {
        return false;
        }
    }
int main()
    {
    try
        {

        if(isElement<double>("3.14d159"))
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
        }
    catch(bad_lexical_cast& E)
        {
        cout<<E.what()<<endl;
        }
    return 0;    
    }

测试:isElement<double>("3.14d159") 输出:NO
测试:isElement<string>("3.14d159") 输出:YES
测试:isElement<long>("314159")     输出:YES
测试:isElement<long>("31.4159")    输出:NO
测试:isElement<char>("314159")     输出:NO



四、源码分析


#ifdef BOOST_NO_STRINGSTREAM        //我们知道stringstream和strstream分别是string和char*结构,lexical_cast考虑很全面的。
#include <strstream>
#else
#include <sstream>
#endif

// bad_lexical_cast是bad_cast的继承,所以很标准,支持和扩充性都很好。
    class bad_lexical_cast : public std::bad_cast 
    {
    public:
        bad_lexical_cast() :
        source(&typeid(void)), target(&typeid(void))
        {
        }
        bad_lexical_cast(
            const std::type_info &s,
            const std::type_info &t) :
            source(&s), target(&t)
        {
        }
//提供了两个返回type_info的函数,为我们跟踪调试类形转换起到很好
        const std::type_info &source_type() const 的做用。
  
 作者: 221.239.187.*  2006-1-2 15:09   回复此发言  
 
2boost的lexical_cast
 
        {
            return *source;
        }
        const std::type_info &target_type() const
        {
            return *target;
        }
        virtual const char *what() const throw()
        {
            return "bad lexical cast: "
                   "source type value could not be interpreted as target";
        }
        virtual ~bad_lexical_cast() throw()
        {
        }
    private:
        const std::type_info *source;
        const std::type_info *target;
    };

type_info的具体用法是:
E.source_type().name()就可能到类型名。

核心转换部分,用的是留的概念,从流内数据的剩余情况与流转换成功与否情况来判断操作是否成功。在不加域时这里就像一个黑盒子。

            bool operator<<(const Source &input)
            {
                return !(stream << input).fail();
            }
            template<typename InputStreamable>
            bool operator>>(InputStreamable &output)
            {
                return !is_pointer<InputStreamable>::value &&
                       stream >> output &&
                       (stream >> std::ws).eof();
            }
            bool operator>>(std::string &output)
            {
                #if defined(BOOST_NO_STRINGSTREAM)
                stream << '\0';
                #endif
                output = stream.str();
                return true;
            }



仅提供该入口,具体实现被封在detail域里面。
    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;
    }


最后
我们可以发现
bad_lexical_cast(typeid(Target), typeid(Source) 与上面
bad_lexical_cast(const std::type_info &s,const std::type_info &t) 
        :source(&s), target(&t)

之间的区别,在我看来是写倒了,不过不影响,也算是个不算bug的bug



五、总结

lexical_cast是强大的,但不是万能的,但在很多情况下他有着独特的优点,安全方便快捷!!!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值