C++ Boost Format超详细讲解

   2023-02-09 学习力0
核心提示:Boost.FormatBoost.Format 提供了函数 std::printf() 的替代品。 std::printf() 源自 C 标准并允许格式化数据输出。但是,它既不是类型安全的,也不是可扩展的。 Boost.Format 提供了一种类型安全且可扩展的替代方案。Boost.Format 提供了一个名为 boost::for

Boost.Format

Boost.Format 提供了函数 std::printf() 的替代品。 std::printf() 源自 C 标准并允许格式化数据输出。但是,它既不是类型安全的,也不是可扩展的。 Boost.Format 提供了一种类型安全且可扩展的替代方案。

Boost.Format 提供了一个名为 boost::format 的类,该类在 boost/format.hpp 中定义。与 std::printf() 类似,将包含用于控制格式的特殊字符的字符串传递给 boost::format 的构造函数。替换输出中这些特殊字符的数据通过运算符 operator% 链接。

示例 7.1。使用 boost::format 格式化输出

#include <boost/format.hpp>
#include <iostream>
int main()
{
  std::cout << boost::format{"%1%.%2%.%3%"} % 12 % 5 % 2014 << '\n';
}

Boost.Format 格式字符串使用放置在两个百分号之间的数字作为实际数据的占位符,这些数据将使用 operator% 进行链接。示例 7.1 使用数字 12、5 和 2014 作为数据创建格式为 12.5.2014 的日期字符串。为了使月份出现在日期的前面,这在美国很常见,可以交换占位符。示例 7.2 进行了此更改,显示 2014 年 5 月 12 日

示例 7.2。带有 boost::format 的编号占位符

#include <boost/format.hpp>
#include <iostream>
int main()
{
  std::cout << boost::format{"%2%/%1%/%3%"} % 12 % 5 % 2014 << '\n';
}

为了使用操纵器格式化数据,Boost.Format 提供了一个名为 boost::io::group() 的函数。

示例 7.3。使用带有 boost::io::group() 的操纵器

#include <boost/format.hpp>
#include <iostream>
int main()
{
  std::cout << boost::format{"%1% %2% %1%"} %
    boost::io::group(std::showpos, 1) % 2 << '\n';
}

Example7.3

示例 7.3 对将与“%1%”关联的值使用操纵器 std::showpos()。因此,此示例将显示 +1 2 +1 作为输出。因为操纵器 std::showpos() 已使用 boost::io::group() 链接到第一个数据值,所以只要显示该值,就会自动添加加号。在这种情况下,格式占位符“%1%”会使用两次。

如果加号仅应显示为 1 的第一个输出,则需要自定义格式占位符。

示例 7.4。带有特殊字符的占位符

#include <boost/format.hpp>
#include <iostream>
int main()
{
  std::cout << boost::format{"%|1$+| %2% %1%"} % 1 % 2 << '\n';
}

Example7.4

​​​ 示例 7.4 就是这样做的。在此示例中,占位符“%1%”的第一个实例被替换为“%|1$+|”。格式的定制不仅仅是添加两个额外的管道符号。对数据的引用也放在管道符号之间,并使用“1$”而不是“1%”。这是将输出修改为 +1 2 1 所必需的。您可以在 Boost 文档中找到有关格式规范的详细信息。 必须为所有占位符或不指定对数据的占位符引用。示例 7.5 仅提供三个占位符之一的引用,这会在运行时生成错误。

示例 7.5。 boost::io::format_error 以防出错

#include <boost/format.hpp>
#include <iostream>
int main()
{
  try
  {
    std::cout << boost::format{"%|+| %2% %1%"} % 1 % 2 << '\n';
  }
  catch (boost::io::format_error &ex)
  {
    std::cout << ex.what() << '\n';
  }
}

Example7.5

示例 7.5 引发了 boost::io::format_error 类型的异常。严格来说,Boost.Format 会抛出 boost::io::bad_format_string。但是,由于不同的异常类都是从 boost::io::format_error 派生的,因此通常更容易捕获这种类型的异常。

示例 7.6 展示了如何在不使用格式字符串中的引用的情况下编写程序。

示例 7.6。没有数字的占位符

#include <boost/format.hpp>
#include <iostream>
int main()
{
  std::cout << boost::format{"%|+| %|| %||"} % 1 % 2 % 1 << '\n';
}

在这种情况下,可以安全地省略第二个和第三个占位符的管道符号,因为它们没有指定任何格式。生成的语法与 std::printf() 非常相似(参见示例 7.7)。

示例 7.7。 boost::format 使用来自 std::printf() 的语法

#include <boost/format.hpp>
#include <iostream>
int main()
{
  std::cout << boost::format{"%+d %d %d"} % 1 % 2 % 1 << '\n';
}

虽然格式可能看起来像 std::printf() 使用的格式,但 Boost.Format 提供了类型安全的优势。格式字符串中的字母“d”不表示数字的输出。相反,它将操纵器 std::dec() 应用于 boost::format 使用的内部流对象。这使得指定对 std::printf() 没有意义的格式字符串成为可能,并且会导致崩溃。

示例 7.8。 boost::format 带有看似无效的占位符

#include <boost/format.hpp>
#include <iostream>
int main()
{
  std::cout << boost::format{"%+s %s %s"} % 1 % 2 % 1 << '\n';
}

std::printf() 只允许 const char* 类型的字符串使用字母“s”。使用 std::printf() 时,“%s”和数值的组合会失败。但是,示例 7.8 完美运行。 Boost.Format 不需要字符串。相反,它应用适当的操纵器来配置内部流。

Boost.Format 既是类型安全的又是可扩展的。只要运算符 operator<< 为 std::ostream 重载,任何类型的对象都可以与 Boost.Format 一起使用。

示例 7.9。 boost::format 具有用户定义的类型

#include <boost/format.hpp>
#include <string>
#include <iostream>
struct animal
{
  std::string name;
  int legs;
};
std::ostream &operator<<(std::ostream &os, const animal &a)
{
  return os << a.name << ',' << a.legs;
}
int main()
{
  animal a{"cat", 4};
  std::cout << boost::format{"%1%"} % a << '\n';
}

Example7.9

示例 7.9 使用 boost::format 将用户定义类型动物的对象写入标准输出。这是可能的,因为流运算符对于动物来说是重载的。

原文地址:https://yamagota.blog.csdn.net/article/details/127279930
 
标签: C++ Boost Format
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • Aurelius vs mORMot vs EntityDAC Delphi 的
    Aurelius vs mORMot vs EntityDAC   Delphi 的 ORM框架:http://www.tmssoftware.com/site/aurelius.asp#product-buy-onlinehttps://synopse.info/fossil/wiki/Synopse+OpenSourcehttps://www.devart.com/entitydac/download.htmlkbmMW  http://www.compo
    02-09
  • 【Ruby】Mac gem的一些坑
    前言自上一次升级MacOS系统后出现jekyll无法构建的问题,当时处理半天。谁知道最近又升级了MacOS,荒废博客多时,今天吝啬写了一篇准备发布,构建报错,问题重新。还是记录下,以防下次升级出问题。问题描述安装jekyll静态博客需要在Ruby环境下运行,于是参照
    02-09
  • iOS oc 调用 swift
    如股票oc要调用swift里面的代码 需要包含固定这个头文件项目名称 LiqunSwiftDemo-Swift.h         #ProjectName#-Swift.h固定的写法swift 目的 是取代oc 但是 不会完全取代 只是前端的替换LiqunSwiftDemo-Swift 点进去 可以看到 所有的swift代码 都产生
    02-09
  • objective-c NSTimer 定时器
    -(void)initTimer{//时间间隔NSTimeInterval timeInterval =3.0 ;//定时器repeats 表示是否需要重复,NO为只重复一次NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:timeInterval target:self selector:@selector(mobileAnimation) userInfo:nil
    02-09
  • Objective-C  日记③ 字符串
    Objective-C 日记③ 字符串
    一、创建字符串、类方法   公式创建NSString  +(id) stringWithFormat:(NSString *) format,……;eg:  NSString *height;  height=[NSString stringWithFormat:@"高度是: %d 长度: %d",10,20];得到的字符串:“高度是: 10 长度: 20” 注意:  省
    02-09
  • Objective-C KVC机制
    Objective-C KVC机制http://blog.csdn.net/omegayy/article/details/7381301全部推翻重写一个版本,这是我在公司内做技术分享的文档总结,对结构、条理做了更清晰的调整。 1.    基本概念MODEL主要是英文文档里面经常出现的一些概念,讲解一下,方便英文
    02-09
  • objective-c 加号 减号 - +
    “加号代表static”是错误的说法,可能跟你那样表达的人其实意思是:“前置加号的方法相当于Java 里面的静态方法”。在Oc中,方法分为类方法和实例方法。前置加号(+)的方法为类方法,这类方法是可以直接用类名来调用的,它的作用主要是创建一个实例。有人把
    02-09
  • Objective-C  日记①
    Objective-C 日记①
    1、Xcode的.m扩展名表示文件含有Object-C代码,C以.c文件,C++以.cpp文件2、头文件声明:C使用:#include,O-C使用#import(当然你也可以使用#include) 3、输出方式:  C:printf("",参数);  O-C:NSLog(@"",参数); 4、布尔类型  C:bool 具有true
    02-09
  • ASP.NET MVC 操作AD 获取域服务器当前用户姓
    #region 根据当前登录域账号 获取AD用户姓名和所在OU目录/// summary/// 根据当前登录域账号 获取AD用户姓名和所在OU目录/// /summary/// param name="searchUser"要搜索的当前用户名/param/// param name="paths"out返回该用户所在OU目录/param/// param nam
    02-09
  • swift和OC - 拆分数组 和 拆分字符串
    1. 拆分数组 /// 根据 数组 截取 指定个数返回 多个数组的集合func splitArray( array: [Date], withSubSize subSize: Int) - [[Date]] {//数组将被拆分成指定长度数组的个数let count = array.count% subSize == 0 ? (array.count/ subSize) : (array.count
    02-08
点击排行