lexical_cast在boost库中的声明
lexical_cast定义在boost命名空间,使用时需要包含头文件<boost/lexical_cast.hpp>.
lexical_cast由一组模版组成,不同的模版对应不同的数据类型转换。下面列出主要的两种。
template <typename Target, typename Source>
inline Target lexical_cast(const Source &arg)
{
Target result = Target();
if (!boost::conversion::detail::try_lexical_convert(arg, result)) {
boost::conversion::detail::throw_bad_cast<Source, Target>();
}
return result;
}
template <typename Target>
inline Target lexical_cast(const char* chars, std::size_t count)
{
return ::boost::lexical_cast<Target>(
::boost::iterator_range<const char*>(chars, chars + count)
);
}
基本用法
int x = boost::lexical_cast<int>("100"); //字符串->整型 100
long y = boost::lexical_cast<long>("2000"); //字符串->长整型 2000
float pai = boost::lexical_cast<float>("3.14159"); //字符串->符点型 3.14159
double e = boost::lexical_cast<double>("2.71828"); //字符串->双精度符点型 2.71828
double r = boost::lexical_cast<double>("1.414abcdefg", 5); //C字符串->双精度符点型(只转前5位) 1.141
std::string str = boost::lexical_cast<std::string>(0.618); //双精度符点型->字符串 0.61799999999999999
std::string str2 = boost::lexical_cast<std::string>(0x10); //16进制数->字符串 16
注:字符串转数字时,字符串中不能包含除数字以外的字符(表示指数的e/E除外)。例如,不能将"123L"、"0x100"这样的字符串转换成数字。
异常处理
当lexical_cast无法执行转换操作时会抛出异常boost::bad_lexical_cast。
lexical_cast在命名空间boost::conversion提供了不抛出异常的版本。
template <typename Target, typename Source>
inline bool try_lexical_convert(const Source& arg, Target& result)
template <typename Target, typename CharacterT>
inline bool try_lexical_convert(const CharacterT* chars, std::size_t count, Target& result)
该系列模板可以用来测试是否可以转换成功。
实现原理
lexical_cast 对转换对象有如下要求:
- 转换起点对象是可流输出的,即定义了 operator<<
- 转换终点对象是可流输入的,即定义了 operator>>
- 转换终点对象必须是可缺省构造和可拷贝构造的
注:C++语言中的内建类型(int,double等)和std::string都满足以上的三个条件。对于自定义类,需要按照这三个条件进行分别实现。
自定义类支持lexical_cast
最主要的是定义输入输出操作符,同时可使用缺省构造函数和拷贝构造函数。
#include <iostream>
#include <boost/lexical_cast.hpp>
class DemoClass
{
public:
std::string str;
};
//重载流输出操作符,可用于转换的起点
std::ostream &operator << (std::ostream &os, const DemoClass &obj)
{
os << obj.str;
return os;
}
//重载流输入操作符,可用于转换的终点
std::istream &operator >> (std::istream &is, DemoClass &obj)
{
is >> obj.str;
return is;
}
int main()
{
DemoClass demoObj = boost::lexical_cast<DemoClass>("HelloWorld"); //demoObj.str = HelloWorld
std::string demoStr = boost::lexical_cast<std::string>(demoObj); //demoStr = HelloWorld
}
注:这里转换过程中如果字符串中间出现空格比如"Hello World",将导致转换失败。原因及解决办法后续提供。
C++11新标准 VS lexical_cast
C++11标准增强了字符串与数字的互操作性。新标准提供了一系列函数
字符串转数字
- stoi
- stol
- stoll
- stof
- stod
数字转字符串
- to_string
使用示例
assert(std::stoi(" 42 ") == 42); //转换int,允许有空格
assert(std::stol("100L") == 100L); //转换long, 支持L等后缀
assert(std::stol("1000 9") == 1000L); //转换long, 后面的被忽略
assert(std::stod("3.14ispi") == 3.14); //转换double, 遇到无效的字符停止
assert(std::to_string(776ul) == "776"); //转换为string
与boost::lexical_cast相比。C++11标准允许字符串里出现非数字字符--会忽略起始的白空格,直到遇到无法转换的字符为止。
lexical_cast不支持空格符原因分析及解决办法
原因分析:http://blog.youkuaiyun.com/ugg/article/details/3381138