boost format使用详解

简述

编程中经常会遇到需要到使用的数据进行格式化的地方,如生成记录日志的字符串,生成发送到网络的完整数据等。

可能需要对int, string, char等进行格式化,常用的方法包括 snprintf, std::string, std::stringstream, boost::format等。

snprintf支持c语言,可能是这几种方式中效率最高的,它们之间的效率对比可以参考 Comparing the performance of a sequence of several generators

但对于效率要求不是非常严苛的场合下,使用其他方法可能会更加方便,这里就要介绍boost::format。

boost::format使用

如果你已经在使用boost库,使用format进行格式化将是一件非常简单的事情。

如前所述,format没有snprintf快,但它是类型安全的。它使用streams构建输出,所以不会存在内存溢出的情况。

format有两种使用风格,一种类似于 printf,另一种使用占位符,类似于c#。

浮点数格式

直接上代码:

const double almostpi = 22.0 / 7.0;
 
// Printf
printf("Pi is %f\n", almostpi);
 
// Boost format with printf syntax
boost::format printf_formatting("Pi is %f\n");
std::cout << printf_formatting % almostpi;
 
// Boost format with positional syntax
boost::format position_formatting("Pi is %1%\n");
std::cout << position_formatting % almostpi;
 
// Output:
// Pi is 3.142857
// Pi is 3.142857
// Pi is 3.14286

显然,format的使用与printf类似,使用 %f 格式化一个浮点数,默认的精度是6位小数。

使用更大的数据可以验证这个结论,如:

const double almostpi = 22.0 / 7.0;
const double distancetosun = 149600000000.0;    // meters
const double earthorbitlength = 2 * almostpi * distancetosun;
 
// Printf
printf("Earth orbit distance is %f meters\n", earthorbitlength);
 
// Boost format with printf syntax
boost::format printf_formatting("Earth orbit distance is %f meters\n");
std::cout << printf_formatting % earthorbitlength;
 
// Boost format with positional syntax
boost::format position_formatting("Earth orbit distance is %1% meters\n");
std::cout << position_formatting % earthorbitlength;
 
// Output:
// Earth orbit distance is 940342857142.857180 meters
// Earth orbit distance is 940342857142.857180 meters
// Earth orbit distance is 9.40343e+011 meters

使得 %1% 占位符时,当数值较大时,会使用科学计数法(大概6-7个字符长度时会使用)。

关于科学计数法

一般而言,只有在使用占位符时,且数值较大时才会转换为科学计数法。如:

boost::format scinotation("Do we use scientific? '%1%'\n");// %llu时也会显示科学计数法
 
for (size_t n=0; n<15; ++n)
{
    double value = 1 * pow(10, n) + 0.5;
    std::cout << scinotation % value;
}
 
// Output:
// Do we use scientific? '1.5'
// Do we use scientific? '10.5'
// Do we use scientific? '100.5'
// Do we use scientific? '1000.5'
// Do we use scientific? '10000.5'
// Do we use scientific? '100001'
// Do we use scientific? '1e+006'
// Do we use scientific? '1e+007'
// Do we use scientific? '1e+008'
// Do we use scientific? '1e+009'
// Do we use scientific? '1e+010'
// Do we use scientific? '1e+011'
// Do we use scientific? '1e+012'
// Do we use scientific? '1e+013'
// Do we use scientific? '1e+014'

另外,在实际使用中,如果使用了不匹配的标记符时,如使用了%llu, 而实际数值却是double时,也会以科学计数法显示。

可以使用 %e 显示指定以科学计数法显示。

格式控制

格式控制的语法为:%[N$][flags][width][.precision]type-char。如:

// Printf
printf("Pi is '%10.2f'\n", almostpi);
 
// Boost format with printf syntax
boost::format printf_formatting("Pi is '%10.2f'\n");
std::cout << printf_formatting % almostpi;
 
// Boost format with positional syntax
boost::format position_formatting("Pi is '%1$10.2f'\n");
std::cout << position_formatting % almostpi;
 
// Output:
// Pi is '      3.14'
// Pi is '      3.14'
// Pi is '      3.14'
常用示例

简单的使用方式,可以直接输出想要的内容:

// 直接输出
cout << boost::format("%s") % "this is what i want" << endl; 

// 结合 string
string s;
s = str(boost::format("%s") % "this is what i want");
cout << s << endl;

// 使用 formater
boost::format fmt("%s");
fmt % "this is what i want";
string s = fmt.str();
cout << s << endl;

// 占位符
cout << boost::format("%1%") % "this is what i want" << endl;
异常处理

format 异常时会throw 异常信息,所以要使用try语句块处理异常,否则程序默认会终止。如:

try
{
	cout << boost::format("%d%d") % 1 << endl;
}
catch (std::exception const &e)
{
	cout << e.what() << endl;
}
catch (...)
{
	cout << "format error" << endl;
}

// output
// boost::too_few_args: format-string refered to more arguments than were passed

参考资料:

Boost::format (and wformat) examples – numbers: int, float, double
Comparing the performance of a sequence of several generators
浅尝boost之format

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值