一直觉得STL与Boost都是很神秘并且高深的,前些天学习了下STL,有了初步的了解,发现真是个好东西,给我们编程真是带来了很大的方便。而且十分的高效,真是让我不舍得不用啊,呵呵。
昨天在网上看了篇关于BOOST的一篇入门文章,收获不小,特此记录下来。
Boost是什么?一套开放源代码、高度可移植的C++库。
它都包括些什么内容呢?
- 正则表达式,可以与POSIX API和Perl语言处理正则表达式的功能相媲美,而且还能支持各种字符类型(如char、wchar_t,甚至还可以是自定义字符类型);
- 多线程,想了很久的跨平台多线程库了;
- 数据结构“图”,再加上即将加入标准的hash_set、hash_map、hash_multiset、hash_multimap等等(事实上不少STL实作,如SGI STL,已经支持以上数据结构),C++对数据结构的支持已近完备;
- python,没错,对Python语言的支持;
- 智能指针,与std::auto_ptr一起善加使用,可杜绝内存泄露,效率更不可和垃圾收集机制GC同日而语;
- 更有循环冗余的CRC、可轻松定义返回多个值函数的元组tuple、可容纳不同类型值的any、对标准库各方面的补充……
- 还在迅速扩大中,部分内容有望进入C++标准库……
在CSDN论坛上经常看到询问如何在字符串类型和数值类型间进行转换的问题,也看到了许多不同的答案。下面先讨论一下从字符串类型到数值类型的转换。
- 如何将字符串"123"转换为int类型整数123?答案是,用标准C的库函数atoi;
- 如果要转换为long类型呢?标准C的库函数atol;
- 如何将"123.12"转换为double类型呢?标准C的库函数atod;
- 如果要转换为long double类型呢?标准C的库函数atold;
- ……
后来有朋友开始使用标准库中的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::endl std::cout<<b<<std::endl; return 0; }
一个函数就简洁地解决了所有的问题。
那么从数值类型到字符串类型呢?
用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; }
跟前面一样简单。
注意事项
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
- 浮点数的精度问题。
std::string s = boost::lexical_cast<std::string>(123.1234567);
#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()) //... }
上述我摘抄了文章的小部分,大概内容都包括进来了。可能还不算上入门,不过觉得很有意思,一定还会继续学习下去。