这次我们先挑个简单实用的Boost组件,看看Boost能给我们带来怎样的便利。

3.1 字符串→数值

在CSDN论坛上经常看到询问如何在字符串类型和数值类型间进行转换的问题,也看到了许多不同的答案。下面先讨论一下从字符串类型到数值类型的转换。

  1. 如何将字符串"123"转换为int类型整数123?答案是,用标准C的库函数atoi;
  2. 如果要转换为long类型呢?标准C的库函数atol;
  3. 如何将"123.12"转换为double类型呢?标准C的库函数atod;
  4. 如果要转换为long double类型呢?标准C的库函数atold;
  5. ……

后来有朋友开始使用标准库中的string类,问这个如何转换为数值?有朋友答曰,请先转换为const char*。我很佩服作答者有数学家的思维:把陌生的问题转化成熟悉的问题。(曾经有一则笑话,好事者问数学家:知道如何烧水吗?答:知道。把水壶加满水,点火烧。又问:如果水壶里已经有水了呢?答:先倒掉,就转化为我熟悉的问题了……)

不,不,这样是C的做法,不是C++。那么,C++该怎么做呢?使用Boost Conversion Library所提供的函数lexical_cast(需要引入头文件boost/lexical_cast.hpp)无疑是最简单方便的。如:

#include <boost/lexical_cast.hpp>
#include <iostream>
int main()
{using boost::lexical_cast;int a = lexical_cast<int>("123");double b = lexical_cast<double>("123.12");std::cout<<a<<std::endlstd::cout<<b<<std::endl;return 0;
}

一个函数就简洁地解决了所有的问题。

3.2 数值→字符串

那么从数值类型到字符串类型呢?

用itoa?不对吧,标准C/C++里根本没有这个函数。即使在Windows平台下某些编译器提供了该函数3,没有任何移植性不说,还只能解决int类型(也许其他函数还可以解决long、unsigned long等类型),浮点类型又怎么办?当然,办法还是有,那就是:sprintf。

char s[100];
sprintf(s, "%f", 123.123456);

不知道诸位对C里的scanf/printf系列印象如何,总之阿炯我肯定记不住那些稀奇古怪的参数,而且如果写错了参数,就会得到莫名其妙的输出结果,调试起来可就要命了(我更讨厌的是字符数组,空间开100呢,又怕太小装不下;开100000呢,总觉得太浪费,心里憋气,好在C++标准为我们提供了string这样的字符串类)。这时候,lexical_cast就出来帮忙啦。

#include <boost/lexical_cast.hpp>
#include <string>
#include <iostream>
int main()
{using std::string;const double d = 123.12;string s = boost::lexical_cast<string>(d);std::cout<<s<<std::endl;return 0;
}

跟前面一样简单。

3.3 异常

如果转换失败,则会有异常bad_lexical_cast抛出。该异常类是标准异常类bad_cast的子类。

#include <boost/lexical_cast.hpp>
#include <iostream>
int main()
{using std::cout;using std::endl;int i;try{i = boost::lexical_cast<int>("abcd");}catch(boost::bad_lexical_cast& e){cout<<e.what()<<endl;return 1;}cout<<i<<endl;return 0;
}

显然“abcd”并不能转换为一个int类型的数值,于是抛出异常,捕捉后输出“bad lexical cast: source type value could not be interpreted as target”这样的信息。

3.4 注意事项

lexical_cast依赖于字符流std::stringstream(会自动引入头文件4),其原理相当简单:把源类型读入到字符流中,再写到目标类型中,就大功告成。例如

int d = boost::lexical_cast<int>("123");

就相当于

int d;
std::stringstream s;
s<<"123";
s>>d;

既然是使用了字符流,当然就有些随之而来的问题,需要特别指出 5。

  • 由于Visual C++ 6的本地化(locale)部分实现有问题,因此如果使用了非默认的locale,可能会莫名其妙地抛出异常。当然,一般情况下我们并不需要去改变默认的locale,所以问题不是很大。
  • 输入数据必须“完整”地转换,否则抛出bad_lexical_cast异常。例如
int i = boost::lexical_cast<int>("123.123"); // this will throw 

便会抛出异常。因为“123.123”只能“部分”地转换为123,不能“完整”地转换为123.123。

  • 浮点数的精度问题。
std::string s = boost::lexical_cast<std::string>(123.1234567);

以上语句预想的结果是得到“123.1234567”,但是实际上我们只会得到“123.123”,因为默认情况下std::stringstream的精度是6(这是C语言程序库中的“前辈”printf留下的传统)。这可以说是boost::lexical_cast的一个bug。怎么办呢?权宜之计,可以这么做:打开头文件<boost/lexical_cast.hpp>,注意对照修改 6:

#include <boost/limits.hpp>
//...
template<typename Target, typename Source>
Target lexical_cast(Source arg) {//...Target result; interpreter.precision(std::numeric_limits<Source>::digits10);if( !(interpreter << arg) ||!(interpreter >> result) ||!(interpreter >> std::ws).eof())//...
}

即可得到正确结果。当然,理论上效率会有一点点损失,不过几乎可以忽略不计。

4 小结


我们已经体验了boost::lexcial_cast。当然,lexical_cast不仅仅局限于字符串类型与数值类型之间的转换:可在任意可输出到stringstream的类型和任意可从stringstream输入的类型间转换。这次的了解尽管很粗略,不过毕竟我们已经“走进Boost”,而不仅仅是“走近”。以后,我们可以自行领略Boost的动人之处啦。

Boost组件lexical_cast相关推荐

  1. boost之lexical_cast

    第一次翻译,虽然是个很简单的函数介绍... 文件boost/lexical_cast.hpp中定义了此函数: [cpp] view plaincopy namespace boost { class  ...

  2. boost:lexical_cast

    概述 顾名思义,lexical_cast库进行"字面值"的转换,类似C中的atoi()函数,可以进行字符串与整数/浮点数之间的字面转换 标准C和c++库提供了许多用于执行此类转换的 ...

  3. boost::convert模块实现lexical_cast的测试程序

    boost::convert模块实现lexical_cast的测试程序 实现功能 C++实现代码 实现功能 boost::convert模块实现lexical_cast的测试程序 C++实现代码 #i ...

  4. C++ boost::lexical_cast

    1. lexical_cast是boost中的一个库, 主要用于数值与字符串的相互转换.boost 的 lexical_cast 能把字符串转成各种 c++ 内置类型,需要包含头文件: #includ ...

  5. PCL第三方库:Eigen, Flann , Qhull, VTK, Boost简介

    前言: PCL作为机器人软件的一个基础类库,融合了基础结构.算法和三维显示.其大量使用第三方库,使用了Boost.Eigen.Flann.VTK.Boost.CUdnn等. 第一预备役:Boost   ...

  6. 读《Boost程序库完全开发指南》

    读<Boost程序库完全开发指南> 2011-05-18 20:47:19|  分类: 读书|举报|字号 订阅 C++确实很复杂,神一样的0x不知道能否使C++变得纯粹和干爽? boost ...

  7. 《Boost程序完全开发指南》

    1.3开发环境 由于Boost大量使用了C++高级特性(如模板偏特化.ADL),因此不是所有的编译器都 能够很好地支持Boost. 在VC集成环境中使用嵌入工程编译的方式需要定义宏BOOST_ALL_ ...

  8. Boost程序库完全开发指南——深入C++“准”标准库(第3版)

    内容简介  · · · · · · Boost 是一个功能强大.构造精巧.跨平台.开源并且完全免费的C++程序库,有着"C++'准'标准库"的美誉. Boost 由C++标准委员会 ...

  9. boost uuid

    uuid:  uuid库是一个小的使用工具,可以表示和生成UUID  UUID是University Unique Identifier的缩写,它是一个128位的数字(16字节),不需要有一个中央认证 ...

  10. boost::convert模块实现算法的测试程序

    boost::convert模块实现算法的测试程序 实现功能 C++实现代码 实现功能 boost::convert模块实现算法的测试程序 C++实现代码 #include <boost/con ...

最新文章

  1. 准确率至上已是过去式,这些趋势在2020年的AI领域更受关注
  2. jsp上传文件名乱码
  3. C语言再学习 -- 声明与定义
  4. 容斥原理 和 欧拉函数
  5. Java zset 应用_Java简单使用redis-zset实现排行榜
  6. shell查询年月日(可以作为crontab判断年月日)
  7. 初学者的React全家桶完整实例
  8. 四大门户金融业务接连中招,流量这把钥匙正被氧化
  9. Rust: Integers: Recreation One
  10. Python电子书下载
  11. 将Go语言编写的HttpServer部署到Docker并推送到DockerHub
  12. 【25】processing-视频(中文)
  13. Django2.0+小程序技术打造微信小程序助手百度云
  14. 爱思国际获戈壁创投数百万美元Pre-A 轮融资,意做菲律宾的分众传媒
  15. 一维数组cvs文件,求数据平均值
  16. STM32入门篇2之外部中断
  17. 全国翻译资格考试 介绍
  18. 小程序城市按首字母排序(如同苹果手机通讯录一样得效果)
  19. 大数据开发基础入门与项目实战(二)Java Web数据可视化之3.Linux概述、安装和结构
  20. 至离开北京的朋友们(r4笔记第99天)

热门文章

  1. 集合框架(数据结构之栈和队列)
  2. linux定时执行脚本
  3. Cookie 和 Session 规则
  4. Facebook怎样开发软件:工程师驱动的文化
  5. (大家发表一下看法)微软研发智能系统 可通过电脑24小时监控员工
  6. Hibernate 主键
  7. servlet-mapping_浅谈servletmapping的机制(二)
  8. 软件功能测试怎么把关指标,软件测试方法经与验.doc
  9. 百炼-2701:与7无关的数
  10. php pdo oci8,PHP516 用phpize增加扩展PDO_OCI和OCI8