【C++20】format格式化输出

C++20 format格式化输出

在C++20之前,格式化能力都依赖于三方格式化库FMT, 而C++20 标准委员会终于在C++标准库引入了格式化功能,从使用方式和风格来看其实就是FMT库转正了

直接使用

包含<format.h>头文件既可以直接使用,类似python 使用{} 作为占位符,{} 会被指定的内容替换

  • 输出内置类型
    #include<format>
    std::cout << std::format("hello {}", "world") << std::endl; // 输出 hello world
    std::cout << std::format("int: {}, bool: {}, double: {},float: {}", 1, true, 1.2, 1.1f); // 输出 int: 1, bool: true, double: 1.2,float: 1.1
    // wstring 测试
    std::wcout << std::format(L"wstring test {}", L"content") << std::endl; // 输出 wstring text conent
    
  • 如果想输出占位符{} 怎么办, 只需要在外层再套一个{} 即可
    std::cout << std::format("{{}}")  << std::endl; // 输出{}
    
  • 指定顺序输出
    如果只使用{} 占位符号,输出的参数将从头到尾逐一替换{} 进行输出,如果需要指定替换顺序,只要在{} 增加序号表明替换顺序
    // 输出 this is seq test, first, second
    std::cout << std::format("this is seq test, {1}, {0}", "second", "first") << std::endl;  
    
  • 格式化输出
    在输出一些整型和浮点数时,我们会有符号输出、位数和对齐的需求,在format中可以通过下列方式实现
    • +:始终带符号输出,正数带+,负数带-
    • -: 只有负数带-
    • 空格: 在正数前面带空格,负数前面带-
    int iValue = 10;
    // 0表示第一个参数,冒号表示格式的开始
    std::format("{0:}, {0:+}, {0:-}, {0: }", iValue) << std::endl; // 输出10, +10, 10,  10
    
    • 0: 冒号后面的0表示填充字符,如果输出的字符宽度小于定义宽度,将使用0进行填充,输出值是0将忽略
    int iValue = 10;
    std::cout << std::format("{:06d}", iValue)<< std::endl; // 输出000010
    
    • #: 对参数输出的形式进行替换,比如对于不同进制的整型数据进行输出时,会在输出参数前面用0b,0x,00的形式进行替换
    // 输出 0b1010, 012, 0xa
    std::cout << std::format("{0:#b}, {0:#o}, {0:#x}", iValue) << std::endl;
    
  • 填充与对齐
    填充与对齐主要包含以下三个字符,分别是>,<,^。
    • >:强制输出,右对齐,使用指定符号填充
    • <: 强制输出,左对齐,使用指定符号填充
    • ^: 可输出中间内容
    int iValue = 10;
    std::cout << std::format("{0:0>6d}, {0:0<6d}, {0:0^6d}", iValue) << std::endl; // 输出000010, 100000, 001000
    
  • 精度与宽度
    使用.和位宽可以指定浮点数的精度和宽度
    float fValue = 3.1415
    std::cout << std::format("{0:.2f}, {0:.6f}", fValue); // 输出 3.14, 3.141500
    

自定义扩展

通过自定义扩展可以让std::format方法格式化输出自定义类型

  • 对std::formatter模板进行模板特化实现,参考cppreference demo的例子
  • 特化之后我们需要实现两个模板函数
    • template<class ParseContext> constexpr ParseContext::iterator parse(ParseContext& ctx) 输出格式解析参数,可以自定义格式,比如'{:#}'格式
    • template<class FmtContext>FmtContext::iterator format(QuotableString s, FmtContext& ctx) const 对内容进行格式化的函数
    • 例子
    struct Person {std::string name { "hhh" };int age { 18 };bool man { false };
    };// 针对person进行模板特化
    template <>
    struct std::formatter<Person> {// 对格式进行解析,这里我们没有定制constexpr auto parse(std::format_parse_context& ctx){auto it = ctx.begin();if (it == ctx.end()) {return it;}if (*it != '}') {throw format_error("invalid param");}return it;}template <class FmtContext>auto format(const Person& person, FmtContext& ctx) const{//  根据我们想要的格式进行输出return std::format_to(ctx.out(), "name is {}, age is {}, sex is {}", person.name, person.age, person.man ? "man" : "woman");}
    };
    
  • 如果不想实现parse 函数,我们也可以继承已有的std::formatter类
    • 例子
    struct Person {std::string name { "hhh" };int age { 18 };bool man { false };
    };// 继承已有的formatter类
    template <>
    struct std::formatter<Person> : std::formatter<std::string> {template <class FmtContext>auto format(const Person& person, FmtContext& ctx) const{return std::format_to(ctx.out(), "name is {}, age is {}, sex is {}", person.name, person.age, person.man ? "man" : "woman");}
    };
    
  • 如果自定义类型是模板类该怎么处理
    • 例子
    template <typename T1, typename T2, typename T3>
    struct CustomeTypeStruct {T1 pName;T2 iAge;T3 iScore;
    };
    // 特化formatter时也增加上自定义模板类的类型
    template <typename T1, typename T2, typename T3, typename CharT>
    struct std::formatter<CustomeTypeStruct<T1, T2, T3>, CharT> : std::formatter<T1, CharT> {template <class FormatContext>auto format(CustomeTypeStruct<T1, T2, T3>& stu, FormatContext& fc){return std::format_to(fc.out(), "T1:{}, T2:{}, T3:{}", stu.pName, stu.iAge, stu.iScore);}
    };

参考

https://mp.weixin.qq.com/s/Rll2rKfpj-6xPlcl5nYaYw
https://en.cppreference.com/w/cpp/utility/format/formatter

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

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

相关文章

plantsimulation编辑图标怎么把图标旋转90°

1、打开要旋转的图标&#xff0c;点击“导出” 2、随意设置个文件名&#xff0c;点击保存。 3、用画图打开&#xff0c;点击旋转后保存。 4、新建一个图标&#xff0c;点击导入&#xff0c;选择刚刚保存的文件即可。

Jmeter性能测试

Jmeter性能测试 一、性能测试介绍 1、什么叫做性能测试&#xff1f; &#xff08;1&#xff09;通过某些工具或手段来检测软件的某些指标是否达到了要求&#xff0c;这就是性能测试 &#xff08;2&#xff09;指通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系…

OpenCV基础——梯度计算、边缘检测、图像金字塔

接上期&#xff1a; OpenCV基础——图像滤波和形态学操作-CSDN博客 一.梯度计算 上贴已经讲过&#xff0c;梯度可以浅显地理解为图像中发生颜色变化的局部区域&#xff0c;也即边界点。本质上是通过构造与卷积核相同的矩阵&#xff0c;计算边缘区域像素点的差异值——也即梯度…

英语学习笔记1

目录 第一部分 例句解析 句子一 原文&#xff1a;Learning English is never easy but always rewarding!翻译&#xff1a;学习英语从来都不容易但总是有回报的&#xff01; 句子二 原文&#xff1a;Sometimes the detailed work of understanding grammar and building v…

测试测试 测试

**非常详细的视频和文字教程&#xff0c;讲解常见的openmv教程包括 巡线、物体识别、圆环识别、阈值自动获取等。非常适合学习openmv、K210、K230等项目 视频合集链接在 openmv教程合集 openmv入门到项目开发 openmv和STM32通信 openmv和opencv区别 openmv巡线 openmv数字识别教…

CSS rem、vw/vh、less

目录 分辨率、视口与二倍图 一、分辨率与像素基础 1. 物理像素&#xff08;Physical Pixels&#xff09; 2. 逻辑像素&#xff08;CSS 像素&#xff09; 二、视口&#xff08;Viewport&#xff09;控制 1. 视口类型 2. 设置理想视口 三、二倍图&#xff08;Retina/HiD…

【数电】半导体存储电路

组合逻辑电路输入和输出之间是确定关系&#xff0c;与之前的历史记录没有任何关系。时序逻辑电路则有相应的存储元件&#xff0c;要把之前的状态保存起来。 要构成时序逻辑电路&#xff0c;必须要有相应的存储元件&#xff0c;第五章讲述相应的存储元件 一、半导体存储电路概…

OPPO手机如何实时翻译会议视频?视频翻译轻松应对多语言场景

在全球化日益深入的今天&#xff0c;跨语言沟通已成为职场和生活中的常见需求。无论是参加国际会议、观看外语视频&#xff0c;还是与海外客户交流&#xff0c;语言障碍都可能成为效率的绊脚石。幸运的是&#xff0c;OPPO手机凭借其强大的功能和智能化设计&#xff0c;为用户提…

28_跨域

目录 promise promise的基本语法 async await try catch promise 静态方法 跨域 跨域的解决方案 1-cors ​编辑 2-jsonp方案 3-代理服务器 promise promise 是一个es6新增的语法 承诺的意思 作用:是专门用来解决回调地狱!!!! promise的基本语法 // 基本语法:// Pr…

LeetCode Hot100 刷题笔记(4)—— 二叉树、图论

目录 一、二叉树 1. 二叉树的深度遍历&#xff08;DFS&#xff1a;前序、中序、后序遍历&#xff09; 2. 二叉树的最大深度 3. 翻转二叉树 4. 对称二叉树 5. 二叉树的直径 6. 二叉树的层序遍历 7. 将有序数组转换为二叉搜索树 8. 验证二叉搜索树 9. 二叉搜索树中第 K 小的元素 …

【漏洞复现】Apache Tomcat partial PUT文件上传反序列化漏洞复现(CVE-2025-24813)

❤️博客主页&#xff1a; iknow181 &#x1f525;系列专栏&#xff1a; 网络安全、 Python、JavaSE、JavaWeb、CCNP &#x1f389;欢迎大家点赞&#x1f44d;收藏⭐评论✍ 0x00 免责声明 本文所述漏洞复现方法仅供安全研究及授权测试使用&#xff1b;任何个人/组织须在合法合规…

BurpSuit抓包失败-基础配置

问题描述&#xff1a;当开启拦截抓包的时候&#xff0c;burpsuite没有反应&#xff0c;好不容易经过一通配置&#xff0c;浏览器出现无法访问的情况。 解决办法&#xff1a; 下载浏览器插件 首先下载一个代理转换插件&#xff1a;Omega&#xff0c;这样比较方便&#xff0c;…

求解AX=XB 方法

一、简介 一文浅谈旋转变换&#xff1a;旋转矩阵、旋转向量、欧拉角、四元数-CSDN博客 在机器人学、计算机视觉和几何学中&#xff0c;经常会遇到求解矩阵方程 AXXB 的问题。这种方程通常出现在坐标系变换、手眼标定&#xff08;Hand-Eye Calibration&#xff09;等场景中。理…

AnimateCC基础教学:随机抽取获奖名单及奖品-V1.0原型版

舞台界面设计: 主轴第一帧代码&#xff1a; this.btnObj.addEventListener("click", updateStage.bind(this)); createjs.Ticker.addEventListener("tick", updateRandom.bind(this)) var _this this; var bPlaying false; var nameList ["张三…

深入了解Linux内核:task_struct结构详解

Linux 操作系统的广袤世界里&#xff0c;进程管理宛如一座大厦的基石&#xff0c;支撑着整个系统的稳定运行与高效运转 。而task_struct结构体&#xff0c;无疑是进程管理这座大厦的核心支柱&#xff0c;它承载着进程的关键信息&#xff0c;贯穿于进程从诞生到消亡的整个生命周…

IsaacLab最新2025教程(7)-引入IK solver控制机器人

机器人控制可以直接给定关节角进行驱动实现功能&#xff0c;完成任务&#xff0c;但是关节角不是很直观而且做teleoperation或者是结合VLA模型时候&#xff0c;用eef pose会更符合直觉一些&#xff0c;isaacsim用的是LulaKinematics&#xff0c;因为IsaacLab现在是ETHZ的团队在…

Vue——常用指令总结、指令修饰符、v-model原理、computed计算属性、watch监听器、ref和$refs

文章目录 一、概念理解二、指令1. 常用内置指令总结2. 常用指令修饰符3. 自定义指令4. v-model原理表单类组件封装 三、补充1. computed计算属性2. watch监视器3. ref和$refs 一、概念理解 【事件处理函数】 事件处理函数应该写到一个跟data同级的配置项&#xff08;methods&a…

求职笔试题

PDD 最长公共子序列 1143-最长公共子序列 class Solution:def longestCommonSubsequence(self, text1: str, text2: str) -> int:"""二维动态规划"""m, n len(text1), len(text2)# dp [[0]* (n1)] * (m1) 这种写法错误&#xff0c;m1行…

【Ragflow】6. Ragflow-plus重磅更新:增加用户后台管理系统

概述 Ragflow本身并不包含用户管理的功能&#xff0c;我在系列前文中&#xff0c;写过一个脚本&#xff0c;用来批量插入用户&#xff0c;并自动加入团队&#xff0c;配置默认模型设置。然而&#xff0c;此方式需要用户安装对应环境&#xff0c;对普通用户并不友好。 因此我开…

什么是贴源库

贴源库的定义与核心概念 贴源库&#xff08;Operational Data Store, ODS&#xff09;是数据架构中的基础层&#xff0c;通常作为数据仓库或数据中台的第一层&#xff0c;负责从业务系统直接抽取、存储原始数据&#xff0c;并保持与源系统的高度一致性。其核心在于“贴近源头”…