format
- 在字符串处理中少不了格式化字符串,C++中传统的格式化函数是C语言的sprintf,但它一个很大的问题就是不安全。
- 因此,在stl中引入了stringstream来实现安全格式化,但是stringstream却远不如sprintf来得直观。
eg
//C风格的格式化字符串
boost::format fmt = boost::format("<%s> %s in the lower case") % text % (is_all_lower? "is": "is not");
string output = fmt.str();
//.net风格的格式化字符串
boost::format fmt = boost::format("<%1%> %2% in the lower case") % text % (is_all_lower? "is": "is not");
cout << fmt << endl;
格式化控制
//传统c语言风格
cout << boost::format("\n\n%s"
"%1t 十进制 = [%d]\n"
"%1t 格式化的十进制 = [%5d]\n"
"%1t 格式化十进制,前补'0' = [%05d]\n"
"%1t 十六进制 = [%x]\n"
"%1t 八进制 = [%o]\n"
"%1t 浮点 = [%f]\n"
"%1t 格式化的浮点 = [%3.3f]\n"
"%1t 科学计数 = [%e]\n"
) % "example :\n" % 15 % 15 % 15 % 15 % 15 % 15.01 % 15.01 % 15.01 << endl;
异常处理
既然boost.format函数是用来代替sprintf的,那么自然就得有异常处理的功能,而不是像sprintf那样死给你看。boost.format的处理方法是抛异常,它在如下两种情况家会抛异常:
- format字符串非法
- format绑定非法
如下代码演示了这两种情形:
try
{
boost::format("<%3");
}
catch(std::exception& err)
{
cout << err.what() << endl;
}
boost::format fmt = boost::format("<%3%> %2% in the lower case")
% text % (is_all_lower? "is": "is not");
try
{
cout << fmt << endl;
}
catch(std::exception& err)
{
cout << err.what() << endl;
}
封装
boost.format是以一个对象,而不是函数来实现的,导致其使用和异常处理起来要麻烦不少,不过,利用c++11的可变参数模板的语法还是可以很容易把它封装成一个可变参数的函数的形式:
string string_fromat(const char* format, …)
需要定义三个重载版本:
template<class TFirst>
void string_format(boost::format& fmt, TFirst&& first)
{
fmt % first;
}
template<class TFirst, class... TOther>
void string_format(boost::format& fmt, TFirst&& first, TOther&&... other)
{
fmt % first;
string_format(fmt, other...);
}
template<class TFirst, class... TOther>
string string_format(const char* format, TFirst&& first, TOther&&... other)
{
boost::format fmt(format);
string_format(fmt, first, other...);
return fmt.str();
}
现在就可以这么用了:
auto output = string_format("<%1%> %2% in the lower case", text, (is_all_lower? "is": "is not"));
所有的异常也都会在该函数中抛出,虽然效率上相对低点,但用起来要舒服点。
lexical_cast
如果转换发生了意外,lexical_cast会抛出一个bad_lexical_cast异常,因此程序中需要对其进行捕捉。
eg:
string s = "123";
int a = lexical_cast<int>(s);
double b = lexical_cast<double>(s);
try
{
int c = lexical_cast<int>("wrong number");
}
catch(bad_lexical_cast & e)
{
printf("%s/r/n", e.what());
}