《白话C++》第10章 Page63 10.3.5 boost::lexical_cast

10.3.5  boost::lexical_cast

boost::lexical_cast用于实现字符串和某些数据类型的转换。常见的如整值与字符串之前的转换:

#include <boost/lexical_cast.hpp>

...
//把字符串转换为......
int i = boost::lexical_cast <int> ("1024");
long l = boost::lexical_cast <long> ("20130");
double d = boost::lexical_cast <double> ("0.123");

//把其他类型转换为字符串
string si = boost::lexical_cast <string> (i);
string sl = boost::lexical_cast <string> (l);
string sd = boost::lexical_cast <string> (d);

可见其用法是:目标数据  =  lexical_cast <目标类型> (源数据),形式和用法都和C++内置的static_cast <> ()等转换操作非常一致。

利用“std::stringstream”,可以模拟lexical_cas的功能,从而加深对它的理解:

#include <sstream>
...

namespace my
{
    template<typename TObj, typename TSrc>
    TObj lexical_cast(TSrc const& src)
    {
        std::stringstream ss;
        ss << src; //吃进源

        TObj obj;
        ss >> obj; //吐出目标

        return obj;
    }
}

把前面测试boost::lexical_cast的代码,相关内容改为“my::lexical_cast”,看到的测试效果一致,虽然还是山寨班子,但所用的技术却和原厂的lexical_cast基本一致。

都是利用了C++的“输入输出流”,可以“吃入”多种类型的数据,再以另外一种类型“吐”出来的基础(有点像魔术盒子),来实现数据在不同类型之间的转换。

C++的“流(stream)”对象也不是什么类型的数据都吃得进去或吐得出来的。用户自定义的数据,它就处理不了,比如有个坐标点:

struct MyPoint
{
    int x, y;
};

原装的lexical_cast暂时也不能把MyPoint的对象转换成字符串:

MyPoint pt;
string smp = boost::lexical_cast <MyPoint> (pt);

怎么办?解决方法是,为MyPoint分别提供输出与输入流的重载即可:

struct MyPoint
{
    int x, y;
};

//输出重载
ostream& operator << (ostream& os, MyPoint const& pt)
{
    os << pt.x << ' ' << pt.y; //两个数用一个空格分隔
    return os;
}

//输入重载
istream& operator >> (istream& is, MyPoint& pt)
{
    is >> pt.x >> pt.y;
    return is;
}

然后先测试一下将MyPoint转成字符串:

void test_custom_lexical_cast()
{
    MyPoint pt;
    pt.x = 90;
    pt.y = -80;

    string s = boost::lexical_cast <string> (pt);
    cout << "pt1: " << s << endl;
}

演示:

成功了!屏幕输出s的值是:“90 -80”。

既然输入重载也已经写好了,那么上面的s再转回MyPoint应该也是妥妥的了。

void test_custom_lexical_cast()
{
    MyPoint pt;
    ...

    string s = boost::lexical_cast <string> (pt);
    ...

    MyPoint pt2;
    pt2 = boost::lexical_cast <MyPoint> (s); 

}

编译,运行,程序居然异常退出了,报告是bad_lexical_cast......

突然想起山寨版本,将前面最后一代码改成“pt2 = my::lexical_cast <MyPoint> (s);”

居然成功了,顺利的将s转换成pt2。

原因很简单,istream默认启用了 std::ios::skipws 参数,当读入两个整数时,中间的空格被自动跳过。我们的代码“is >> pt.x >> pt.y”利用了这个特性,能够正确地从流中读出 x 和 y 的值。

boost::lexical_cast所使用的流,为了严格起见,主动关闭了 std::ios::skipws参数。所以我们的代码做如下修改:

/* 根据boost::lexical_cast内部流的要求,
重写MyPoint输入流的操作 */
istream& operator >> (istream& is, MyPoint& pt)
{
//    is >> pt.x >> pt.y;

    is >> pt.x;
    is.get(); //跳过空格
    is >> pt.y;

    return is;
}

再次运行,依然成功

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值