用boost::format来格式化字符串

转: 用boost::format来格式化字符串

在字符串处理中少不了格式化字符串,C++中传统的格式化函数是C语言的sprintf,但它一个很大的问题就是不安全。因此,在stl中引入了stringstream来实现安全格式化,但是stringstream却远不如sprintf来得直观。例如,对如如下代码:

    char text[]="hello";    
    bool is_all_lower = boost::algorithm::all(text, is_lower());

    char output[128];
    sprintf(output, "<%s> %s in the lower case", text, (is_all_lower? "is""is not"));

如果把最后两句format的函数用stringstream来写的话,可读性是远不如sprintf的。

    stringstream output;
    output << "<" << text << "> "
        << (is_all_lower)? "is""is not"
        << " in the lower case";

boost引入了一个提供类似.net中的string.format的方式提供格式化字符串的函数,用它来格式化的话就是如下形式:

    boost::format fmt = boost::format("<%s> %s in the lower case") % text % (is_all_lower? "is""is not");
    string output = fmt.str();

前面的例子中演示的是C风格的格式化字符串,boost.format也提供了类似.net风格的格式化字符串方式:

    boost::format fmt = boost::format("<%1%%2% in the lower case") % text % (is_all_lower? "is":"is not");
    cout << fmt << endl;

这种方式更容易看到参数在格式化字符串中的位置,推荐这种形式。不过它的起始坐标是1而不是0,用惯了.net的string.format的朋友需要注意下。

格式化控制

格式化语法为: [ N$ ] [ flags ] [ width ] [ . precision ] type-char。也提供了C语言和.net两种风格。

    //传统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; 

    //.net
的风格

    cout << boost::format("%1%" 
            "%1t 
十进制
 = [%2$d]\n" 
            "%1t 
格式化的十进制 = [%2$5d]\n" 
            "%1t 
格式化十进制,前补'0' = [%2$05d]\n" 
            "%1t 
十六进制 = [%2$x]\n" 
            "%1t 
八进制 = [%2$o]\n" 
            "%1t 
浮点 = [%3$f]\n" 
            "%1t 
格式化的浮点 = [%3$3.3f]\n" 
            "%1t 
科学计数 = [%3$e]\n" 
            ) % "example :\n" % 15 % 15.01 << endl;

异常处理

既然boost.format函数是用来代替sprintf的,那么自然就得有异常处理的功能,而不是像sprintf那样死给你看。boost.format的处理方法是抛异常,它在如下两种情况家会抛异常:

  1. format字符串非法
  2. 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 charformat, …)

需要定义三个重载版本:

    template<class TFirst>
    void string_format(boost::formatfmtTFirst&& first)
    {
        fmt % first;
    }

    template<class TFirstclass... TOther>
    void string_format(boost::formatfmtTFirst&& firstTOther&&... other)
    {
        fmt % first;
        string_format(fmtother...);
    }

    template<class TFirstclass... TOther>
    string string_format(const charformatTFirst&& firstTOther&&... other)
    {
        boost::format fmt(format);
        string_format(fmt, firstother...);
        return fmt.str();
    }

现在就可以这么用了:

    auto output = string_format("<%1%> %2% in the lower case", text, (is_all_lower? "is""is not"));

所有的异常也都会在该函数中抛出,虽然效率上相对低点,但用起来要舒服点。

PS:可变参数模板的特性在vc 2012中还不支持,不过微软已经发布了一个CTP版本的编译器使得可以在vc 2012中使用该特性,应该在下个update版本或sp1中就会正式支持。gcc可以完美支持,windows下也可以通过MinGW使用该特性。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值