C++ 好用的格式化库--fmt

背景

fmt 库是一个开源的 C++ 格式化库,它提供了一种简洁、安全和高效的方式来进行字符串格式化。
该库的设计目标是提供与 Python 的字符串格式化语法类似的功能,同时保持 C++ 的类型安全性和性能。

下载与安装

官网下载

fmt 官网地址:https://fmt.dev/latest/index.html。
可以从官网或者 GitHub 存储库 (https://github.com/fmtlib/fmt) 下载源代码并手动构建。

使用 vcpkg 安装

fmt 也可以通过 vcpkg 包管工具进行下载安装:

header-only

fmt 库也支持 header-only 方式使用,需要设置 FMT_HEADER_ONLY 宏。

#define FMT_HEADER_ONLY 
#include "fmt/core.h"

hello world

下面是一个使用C++fmt库的简单示例:

#include "fmt/core.h"int main()
{fmt::print("hello {}", "world");return 0;
}

运行上述代码,将输出以下结果:

基本格式化语法

参数替换

类似于 printf 的 % 占位符输出,fmt 使用大括号替代参数,且和参数类型无关:

#include "fmt/core.h"int main()
{fmt::print("hello {}", 123);return 0;
}

运行上述代码,将输出以下结果:

按位置替换参数

参数位置默认从 0 开始:

#include "fmt/core.h"int main()
{fmt::print("{0}+{1}={2}", 1,2,3);return 0;
}

运行上述代码,将输出以下结果:

如果没有指定位置,默认从 0 往后依次替换:

fmt::print("{}+{}={}", 1,2,3);

运行上述代码,将输出以下结果:

参数格式化

可以要按指定格式替换指定位置的参数,用 {位置:格式} 的形式表示替换内容。

指定填充字符

可以指定字符串长度,若长度不够则使用指定的字符进行填充。

右侧填充

使用 < 表示右填充,即文本居左:

fmt::print("{0:*<10}", "hello");

运行结果如下:

左侧填充

使用 > 表示左填充,即文本居右:

fmt::print("{0:*>10}", "hello");

运行结果如下:

两边填充

使用 ^ 表示在两层填充,即文本居中:

fmt::print("{0:*^10}", "hello");

运行结果如下:

默认填充字符

可以指定填充字符时,默认使用空格进行填充:

fmt::print("{0:>10}\n{1:>10}", "hello","world");

运行结果如下:

动态设置字符串长度

字符串的长度也可以用参数指定:

fmt::print("{0:>{1}}\n{2:>10}", "hello",20,"world");

运行结果如下:

按精度格式化

使用 . 表示精度格式化。

格式化字符串长度

使用 .n 表示把字符串的长度格式为 n :

fmt::print("{0:.4}", "abcdefg");

运行结果如下:

格式化浮点数长度

使用 .n 也可以用来表示把浮点数长度为 n :

fmt::print("{0:.3}", 1.23456);

运行结果如下:

格式化小数位数

使用 .nf 表示把浮点数小数位数格式化为 n:

动态设置精度

精度值也可以通过参数动态设置:

fmt::print("{0:.{1}f}", 3.141596,2);

运行结果如下:

数字正负号格式化

用于格式化数字正负符号显示。

仅负数显示符号

使用 - 表示仅负数显示符号:

fmt::print("正数:{0:}\n负数:{1:}", 30,-20);

运行结果如下:

正负数都显示符号:

使用 + 表示正负数字都显示符号:

fmt::print("正数:{0:+}\n负数:{1:+}", 30,-20);

运行结果如下:

数字进制格式化

格式化为10进制

使用 d 表示格式化数字为10进制进行显示:

fmt::print("10进制:{0:d}", 10);

运行结果如下:

格式化为2进制

使用 b 表示格式化数字为2进制进行显示:

fmt::print("2进制:{0:b}", 10);

运行结果如下:

格式化为16进制

使用 x 表示格式化数字为16进制进行显示:

fmt::print("16进制:{0:x}", 10);

运行结果如下:

显示进制符号

在进制符号前加 # 可以在进制格式化时增加符号标记:

fmt::print("16进制:{0:#x}", 10);

运行结果如下:

格式化数字长度

在进制符号前可以增加长度表示,长度不够补 0 :

fmt::print("{0:08d}", 10);

运行结果如下:

fmt 库使用

格式化内容到字符串

fmt::format 方法会把格式化的结果转为字符串:

#include <iostream>
#include "fmt/core.h"int main()
{auto res = fmt::format("hello {}", "world");std::cout << res << std::endl;return 0;
}

运行结果如下:

格式化内容到迭代器

fmt::format_to 方法可以把内容格式化到指定的迭代器:

#include "fmt/core.h"int main()
{std::string s;fmt::format_to(std::back_inserter(s), "hello {}", "world");std::cout << s << std::endl;return 0;
}

运行结果如下:

格式化内容到控制台

fmt::print 方法把格式化结果输出到控制台显示:

fmt::print("hello {}", "world");

fmt 库使用进阶

使用参数格式化

命名参数

使用 fmt::arg 可以构建一个命名参数:

fmt::print("{a:*<10}{b:#x}", fmt::arg("a", "hello"), fmt::arg("b", 100));

运行结果如下:

参数列表

fmt::vformat 支持使用参数列表进行格式化:

#include <iostream>
#include "fmt/core.h"int main()
{const fmt::format_args args = fmt::make_format_args(fmt::arg("a", "hello"),fmt::arg("b", 100));const auto s = fmt::vformat("{a:*<10}{b:#x}", args);std::cout << s << std::endl;return 0;
}

运行结果如下:

同样 fmt::vprint 也支持传入参数列表进行格式化。

自定义类型格式化

特例化 formatter< T > 方式

特例化 fmt::formatter< T > 并且实现其 parse 和 format 方法,可以实现对自定义类型的格式化。

自定义数据类型

使用以下自定义类型作为示例:

struct my_struct
{int id;std::string name;
};

特例化 fmt::formatter< T >

特例化 fmt::formatter< T > 并实现其 parse 和 format 方法:

template <>
struct fmt::formatter<my_struct>
{char presentation = 'f';auto parse(fmt::format_parse_context &ctx) -> decltype(ctx.begin()){auto it = ctx.begin(), end = ctx.end();if (it != end && (*it == 'f' || *it == 'i')) presentation = *it++;if (it != end && *it != '}') throw "invalid format";return it;}template <typename FormatContext>auto format(const my_struct & ms, FormatContext &ctx) const -> decltype(ctx.out()){return presentation == 'f'? fmt::format_to(ctx.out(), "[my_struct]id={},name= {}", ms.id, ms.name): fmt::format_to(ctx.out(), "[my_struct]id={}", ms.id);}
};

使用示例

int main()
{my_struct ms{ 0,"hello" };fmt::print("my_struct f 格式化:{0:f}\nmy_struct i 格式化:{0:i}", ms);return 0;
}

运行结果如下:

继承现有 formatter 类

也可以通过继承现有的 formatter 实现自定义类的格式化:

#include "fmt/core.h"
#include "fmt/format.h"struct my_struct
{int id;std::string name;
};
template <>
struct fmt::formatter<my_struct> : formatter<string_view>
{auto format(my_struct ms, format_context &ctx) const{const auto fmt_str = fmt::format("[my_struct]id={}", ms.id);const fmt::string_view sv(fmt_str.data(),fmt_str.size());return formatter<string_view>::format(sv, ctx);}
};
int main()
{my_struct ms{ 0,"hello" };fmt::print("{}", ms);return 0;
}

运行结果如下:

枚举类型格式化

对于枚举类型 fmt 提供了 format_as 接口用于类型转换。

转底层数据类型

使用 fmt::underlying 可以把枚举值转为底层数据类型:

#include "fmt/core.h"
#include "fmt/format.h"enum class my_enum
{red = 0,green,blue
};
auto format_as(my_enum e)
{return	fmt::underlying(e);
}
int main()
{fmt::print("{}", my_enum::green);return 0;
}

运行结果如下:

转其他类型

也可以在 format_as 把枚举值转为其他类型:

#include "fmt/core.h"
#include "fmt/format.h"enum class my_enum
{red = 0,green,blue
};
auto format_as(my_enum e)
{switch (e){case my_enum::red:return "red";case my_enum::green:return "green";case my_enum::blue:return "blue";}
}
int main()
{fmt::print("{}", my_enum::green);return 0;
}

运行结果如下:

容器元素格式化

fmt::join 可以定义分隔符对容器中的元素进行格式化:

int main()
{std::string s = "1234567";fmt::print("{}", fmt::join(s, ", "));return 0;
}

运行结果如下:

对于 std::tuple 可以直接进行格式化操作:

#include "fmt/core.h"
#include <fmt/ranges.h>
int main()
{std::tuple<int, char> t = { 1, 'a' };fmt::print("{}", t);return 0;
}

运行结果如下:

微信搜索“编程猿来如此”关注公众号获取更多内容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/48968.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

elementUI自定义上传文件 前端后端超详细过程

下面是使用Element UI自定义上传文件的前后端详细过程&#xff1a; 前端过程&#xff1a; 引入Element UI组件库&#xff1a;在前端项目中引入Element UI库&#xff0c;可以通过CDN引入或者通过npm安装并导入。 创建上传组件&#xff1a;在前端代码中创建一个上传组件&#x…

opencv 进阶17-使用K最近邻和比率检验过滤匹配(图像匹配)

K最近邻&#xff08;K-Nearest Neighbors&#xff0c;简称KNN&#xff09;和比率检验&#xff08;Ratio Test&#xff09;是在计算机视觉中用于特征匹配的常见技术。它们通常与特征描述子&#xff08;例如SIFT、SURF、ORB等&#xff09;一起使用&#xff0c;以在图像中找到相似…

Git相关命令

SSH密钥文件 Github里面S设置SH公钥有两者选择方式 账号下的每个仓库都设置一个公钥&#xff0c;因为GitHub官方要求每个仓库的公钥都不能相同&#xff0c;所以每个账号都要搞一个密钥&#xff08;很麻烦&#xff09;给账号分配一个公钥&#xff0c;然后这个公钥就可以在这个…

如何将pdf文件转换成word文档?

如何将pdf文件转换成word文档&#xff1f;PDF文档是我们日常办公中最为常用的电子文档格式的文件&#xff0c;也是在会议、教育培训以及商业营销中经常使用的文档格式。所以说PDF文档的功能较强&#xff0c;且应用场景较多。但是也有例外的时候&#xff0c;比如我们需要将PDF文…

Vue的五种方法实现加减乘除运算

五种方法的详细说明&#xff1a; 计算属性&#xff08;Computed Properties&#xff09;&#xff1a; 计算属性是Vue.js提供的一种便捷的属性&#xff0c;它根据依赖的数据动态计算出一个新的值。计算属性的值会被缓存&#xff0c;只有当依赖的数据发生变化时&#xff0c;才会…

前端面试总结心得

1.放在HTML里的哪一部分JavaScripts会在页面加载的时候被执行&#xff1f; A、文件头部位置&#xff1b;B、文件尾&#xff1b;C、<head>标签部分&#xff1b;D、<body>标签部分 &#xff08;正确答案D&#xff09; 2.队列和栈的区别是什么&#xff1f; 答案&am…

python判断ip所属地区 python 判断ip 网段

前言 IP地址是互联网中唯一标识一个设备的地址&#xff0c;有时候需要判断一个IP地址所属的地区&#xff0c;这就需要用到IP地址归属查询。本文将介绍Python如何通过IP地址查询所属地区并展示代码。 一、 IP地址归属查询 IP地址归属查询又称IP地址归属地查询、IP地址归属地定…

框架分析(2)-React

框架分析&#xff08;2&#xff09;-React 专栏介绍React核心思想关键特性和功能组件化开发单向数据流JSX语法强大的生态系统 优缺点分析优点缺点 专栏介绍 link 主要对目前市面上常见的框架进行分析和总结&#xff0c;希望有兴趣的小伙伴们可以看一下&#xff0c;会持续更新的…

火山引擎发布自研视频编解码芯片 压缩效率提升30%

8月22日&#xff0c;火山引擎视频云宣布其自研的视频编解码芯片已成功出片。经验证&#xff0c;该芯片的视频压缩效率相比行业主流硬件编码器可提升30%以上&#xff0c;未来将服务于抖音、西瓜视频等视频业务&#xff0c;并将通过火山引擎视频云开放给企业客户。 火山引擎总裁…

【真实案例】解决后端接口调用偶尔超时问题

文章目录 背景分析代码分析二次日志分析排查Gateway服务解决解决办法1:添加重试机制解决办法2:优化网关内存分配解决办法3:调整OOM策略背景 项目从虚拟机迁移到k8s云原生平台(RainBond)后,发现偶尔会出现接口调用超时的问题。 统计了一下从上线到现在近一个月的调用失败…

基于Springboot+Thymeleaf学生在线考试管理系统——LW模板

摘 要 随着当前大数据时代的飞速发展&#xff0c;信息技术以及数据科学不断的普及&#xff0c;教育界也随之更新换代。无粉尘黑板以及电子化考试都已经是在各种学校中普及使用&#xff0c;而且因为操作简单以及对环境没有任何影响&#xff0c;这也将是未来发展的重大趋势。而由…

springMVC Unix 文件参数变更漏洞修复

错误信息如下&#xff1a; 解决方案&#xff1a; 原因&#xff1a;未对用户输入正确执行危险字符清理 未检查用户输入中是否包含“…”&#xff08;两个点&#xff09;字符串&#xff0c;比如 url 为 /login?action…/webapps/RTJEKSWTN26635&typerandomCode cookie为Coo…

Spring Boot 整合MyBatis(超详细)

&#x1f600;前言 本篇博文关于Spring Boot 整合MyBatis&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大家&#xff0c;您的满意是我的动力&#x…

R语言03-R语言中的矩阵

概念 在R语言中&#xff0c;矩阵&#xff08;Matrix&#xff09;是一个二维的数据结构&#xff0c;由行和列组成&#xff0c;其中所有元素必须具有相同的数据类型。矩阵可以用于存储数值型数据&#xff0c;常用于线性代数运算、统计计算以及数据处理等领域。 代码示例 # 创建…

从零学算法160

**160.**给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 示例 1&#xff1a; 输入&#xff1a;intersectVal 8, listA [4,1,8,4,5], listB [5,6,1,8,4,5], skipA 2, ski…

AJ-Captcha行为验证在vue中的使用

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 项目场景&#xff1a;由原先的验证码校验升级为行为验证校验 使用方法 提示&#xff1a;参考文档&#xff1a; 参考文档&#xff1a;vue使用AJ-Captcha文档 gitee地址&#xff1a;AJ-Captcha &…

FFmpeg解码32k大分辨率出现如下错误:Picture size 32768x32768 is invalid

最近找到一张32k的jpeg图片&#xff0c;尝试用ffmpeg来进行解码&#xff0c;命令如下&#xff1a; ffmpeg -i enflame_32768-32768-420.jpg 32.yuv结果出现Picture size 32768x32768 is invalid的错误&#xff1a;

uniapp-滑块验证组件wo-slider

wo-slider是一款支持高度自定义的滑块验证组件&#xff0c;采用uniapp-vue2编写 采用touchstart、touchmove、touchend事件实现的滑块组件,支持H5、微信小程序&#xff08;其他小程序未试过&#xff0c;可自行尝试&#xff09; 可到插件市场下载尝试&#xff1a; https://ext.…

Docker搭建个人网盘、私有仓库

1、使用mysql:5.6和 owncloud 镜像&#xff0c;构建一个个人网盘 [rootlocalhost ~]# docker pull mysql:5.6 [rootlocalhost ~]# docker pull owncloud [rootlocalhost ~]# docker run -itd --name mysql --env MYSQL_ROOT_PASSWORD123456 mysql:5.6 [rootlocalhost ~]# doc…

RESTful API,以及如何使用它构建 web 应用程序

RESTful API是一种基于HTTP协议的API设计风格&#xff0c;它的核心思想是将资源作为 API 的核心&#xff0c;使用 HTTP 的 GET、POST、PUT、DELETE 等方法对这些资源进行操作&#xff0c;并通过 URL 来定位资源。 RESTful API的特点包括&#xff1a; 资源是 API 的核心使用 H…