当前位置: 首页 > news >正文

C++格式化库fmt使用方法

1. 格式化库fmt简介

fmt github地址
api说明
格式化参数说明

内容的格式化,体现在代码中主要表现为字符串、基本类型、自定义类型的拼接。例如说打印日志、拼接变量等。C++中我们会经常使用类似printf,snprintf(C风格使用不方便),std::string.append(繁琐), std::iostream(慢)这些来实现格式化。
fmt库是C++语法开发的格式化库,被诸多项目使用。相比于printf,stream主要兼具以下几个优点:

  1. 速度更快,更安全
  2. 支持位置参数
  3. 支持自定义对象的格式化
  4. python风格,更简洁

2. fmt的基本使用

fmt库是python风格的格式化库,语法被{}包裹起来。语法总体上分为两段 {id:format}, id是位置参数或者命名参数,format是具体的格式化说明,包括对齐、宽度、精度、填充等。详细语法说明可以参考: syntax

2.1 基本替换

  • 基本替换
fmt::format("id={},cost={}ms,ret={}", "5d84f51115d6f0d69dc299d280a016a4", 30.0, 0);
// id=5d84f51115d6f0d69dc299d280a016a4,cost=30ms,ret=0
  • 带位置参数的替换
fmt::print("I'd rather be {1} than {0}.\n", "right", "happy");
// I'd rather be happy than right.

2.2 参数格式化

format_spec ::=  [[fill]align][sign]["#"]["0"][width]["." precision]["L"][type]
fill        ::=  <a character other than '{' or '}'>
align       ::=  "<" | ">" | "^"
sign        ::=  "+" | "-" | " "
width       ::=  integer | "{" [arg_id] "}"
precision   ::=  integer | "{" [arg_id] "}"
type        ::=  "a" | "A" | "b" | "B" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" |"o" | "p" | "s" | "x" | "X" | "?"
  • 格式化时间和日期
 auto now = std::chrono::system_clock::now();fmt::print("Date and time: {}\n", now);fmt::print("Time: {:%H:%M}\n", now);
  • 格式化STL
  std::vector<int> v = {1, 2, 3};fmt::print("{::#b}\n", v);// [0b1, 0b10, 0b11] 转换成2进制std::map<std::string, std::string> kv{{"k1", "v1"}};fmt::print("{}", kv);// {"k1": "v1"}
  • 对齐、填充、精度、宽度
    例如我要将cost值格式化为小数点后保留3位,总长度为8,不足地方在左侧使用0填充。
    参照上面的语法,fill=0, align=>(选择左对齐),width=8,precision=3,type=f
    fmt::print("cost={0:0>08.3f}\n", 1.2);
  • 整数进制
    例如需要将请求id转换成16进制,固定长度为8位。
    fmt::print("id={:08x}\n", 12567);

2.3 命名参数

使用fmt::arg

  std::string ret = "ret:";fmt::format_to(std::back_inserter(ret), "id={}", "123");fmt::print("named {ret:}", fmt::arg("ret", ret));

2.4 自定义类型的格式化

实际使用过程中,服务中可能存在一些复杂的结构体,我们希望在日志中打印出该结构体的一些信息便于追踪。例如我们有一个这样的结构体,表示后端服务在处理请求时的一个记录。

struct ServiceContext {std::string ip;float cost;int ret;int id;std::string ToString() const {return fmt::format("[{:08x}] client={}, cost={:.2f}", id, ip, cost);}
};

在打印记录的时候我们需要获取该结构体的一些具体信息,通常我们可能会写一个ToString() 或者DebugString()的接口,返回具体的信息。但是有时我们不能直接修改这些结构,也可以在fmt库中位该类型定义format_as接口.

std::string format_as(const ServiceContext &ctx) { return fmt::format("[{:08x}] client={}, cost={:.2f}", ctx.id, ctx.ip, ctx.cost);
}

当然,fmt库也支持为自定义类型定义各种语法,不再深入讨论。

相关文章:

  • win10下使用docker和VMware
  • 高考毕业季--浅谈自己感想
  • 基于PPO的强化学习超级马里奥自动通关
  • 【Python】数据处理:Matplotlib绘图
  • mysql和redis的双写一致性问题
  • Qt | QDataStream 类(数据流)
  • 敏捷=996/007?现实是……
  • 【通过新能源汽车的智慧数字底盘技术看计算机的相关技术堆栈?以后是软硬结合的全能程序员的天下,取代全栈(前后端都会的全栈程序员)】
  • 怎么做才能推动产业园区的数字化转型和升级
  • 独孤思维:每天做着自己不喜欢的工作,你不难受吗
  • uniapp面试题
  • 【docker hub镜像源失效】2024年6月6日 docker 国内镜像源失效
  • RestTemplate远程请求的艺术
  • echarts写某个市地图
  • 如何进行LLM大模型推理优化
  • 时间复杂度分析经典问题——最大子序列和
  • [译] 怎样写一个基础的编译器
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • Consul Config 使用Git做版本控制的实现
  • overflow: hidden IE7无效
  • React-flux杂记
  • Service Worker
  • sublime配置文件
  • 搞机器学习要哪些技能
  • 关于for循环的简单归纳
  • 聊聊directory traversal attack
  • 前端 CSS : 5# 纯 CSS 实现24小时超市
  • 入职第二天:使用koa搭建node server是种怎样的体验
  • 我建了一个叫Hello World的项目
  • 一文看透浏览器架构
  • 用element的upload组件实现多图片上传和压缩
  • 优化 Vue 项目编译文件大小
  • FaaS 的简单实践
  • ​第20课 在Android Native开发中加入新的C++类
  • ​一些不规范的GTID使用场景
  • # 学号 2017-2018-20172309 《程序设计与数据结构》实验三报告
  • (7)STL算法之交换赋值
  • (Java岗)秋招打卡!一本学历拿下美团、阿里、快手、米哈游offer
  • (TipsTricks)用客户端模板精简JavaScript代码
  • (ZT) 理解系统底层的概念是多么重要(by趋势科技邹飞)
  • (精确度,召回率,真阳性,假阳性)ACC、敏感性、特异性等 ROC指标
  • (原創) 如何安裝Linux版本的Quartus II? (SOC) (Quartus II) (Linux) (RedHat) (VirtualBox)
  • (转)http协议
  • (转)程序员疫苗:代码注入
  • (转)创业的注意事项
  • .NET 5种线程安全集合
  • .Net core 6.0 升8.0
  • .Net Remoting常用部署结构
  • .Net Winform开发笔记(一)
  • .net 无限分类
  • .NET 线程 Thread 进程 Process、线程池 pool、Invoke、begininvoke、异步回调
  • .NET/C# 判断某个类是否是泛型类型或泛型接口的子类型
  • .NET委托:一个关于C#的睡前故事
  • .secret勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复
  • @Builder用法