C++ 20新特性之std::format

为什么需要std::format

在C++ 20之前,我们通常使用printf、stringstream、cout等流对象,并结合各种流操作符(比如:<<)和格式化控制符(比如:std::setw、std::setprecision等)来实现格式化输出。这种方式虽然灵活,但使用起来却相当繁琐,特别是在处理复杂的格式化需求时。

在下面的示例代码中,我们使用cout来输出一句文字信息,其中包括姓名和年龄。可以看到,cout的写法比较丑陋和繁琐,不够简洁。

C++ 复制代码
#include <iostream>
#include <string>
using namespace std;

int main()
{
    string strName = "Mike";
    int nAge = 18;
    cout << "Name is " << strName << ", Age is " << nAge << "." << endl;
    return 0;
}

为了解决这一问题,C++ 20中引入了std::format。std::format借鉴了Python中str.format()函数的思想,通过占位符和格式化选项来实现灵活的格式化输出。与printf、cout等相比,std::format具有更强的类型安全性和可读性,同时也支持更多的格式化选项。

基本用法

std::format函数的基本形式如下。

C++ 复制代码
std::string strText = std::format("格式化字符串", 参数1, 参数2, ...);

其中,"格式化字符串"包含普通文本以及由大括号{}包围的占位符,这些占位符会被后面的参数值替换。注意:参数的顺序应当与占位符的顺序保持一致。

下面的示例代码与上面提到的代码功能相同,但使用std::format简化了输出。运行这段代码,将会输出:"Name is Mike, Age is 18.",其中的两个大括号{}被strName和nAge替换。

C++ 复制代码
#include <iostream>
#include <string>
#include <format>
using namespace std;

int main()
{
    string strName = "Mike";
    int nAge = 18;
    cout << format("Name is {}, Age is {}.", strName, nAge) << endl;
    return 0;
}

使用索引

我们还可以通过索引指定参数的位置,这在需要改变输出顺序时非常有用,具体用法可参考下面的示例代码。

C++ 复制代码
#include <iostream>
#include <string>
#include <format>
using namespace std;

int main()
{
    string strName = "Mike";
    int nAge = 18;
    // 索引0对应strName,索引1对应nAge
    cout << format("Name is {0}, Age is {1}.", strName, nAge) << endl;
    // 索引0对应nAge,索引1对应strName
    cout << format("Name is {1}, Age is {0}.", nAge, strName) << endl;
    return 0;
}

格式化数字

std::format支持数字的格式化,比如:保留小数位数、添加前导零等,具体用法可参考下面的示例代码。

C++ 复制代码
#include <iostream>
#include <format>
using namespace std;

int main()
{
    const double PI = 3.14159265;
    // 输出3位小数的PI:3.142
    cout << format("PI: {:.3f}", PI) << endl;
    // 输出前导零,总宽度为5:00066
    cout << format("Number: {:05}", 66) << endl;
    return 0;
}

对齐与填充

std::format引入了一套丰富的格式化选项,允许我们控制字符串的对齐、填充以及其它格式化细节。对齐方法主要有三种:左对齐、居中对齐、右对齐。

{:<width}:左对齐,确保总宽度至少为width,不足部分使用空格填充。

{:>width}:右对齐,确保总宽度至少为width,不足部分使用空格填充。

{:^width}:居中对齐,确保总宽度至少为width,不足部分使用空格填充。

另外,除了使用默认的空格作为填充字符外,我们还可以指定其他字符进行填充,使用方式如下。

{:fillchar<width.precision}

在下面的示例代码中,我们使用format演示了左对齐、居中对齐、右对齐的效果。其中,<、^、>分别代表左对齐、居中对齐和右对齐,数字10表示总宽度,#代表填充字符。

C++ 复制代码
#include <iostream>
#include <format>
using namespace std;

int main()
{
    // 输出:Left       |   Center   |      Right
    cout << format("{:<10} | {:^10} | {:>10}\n", "Left", "Center", "Right");
    // 输出:66         |    100     |       1024
    cout << format("{:<10} | {:^10} | {:>10}\n", 66, 100, 1024);
    // 输出:|Left######|##Center##|#####Right|
    cout << format("|{:#<10}|{:#^10}|{:#>10}|\n", "Left", "Center", "Right");
    return 0;
}

💡 如果想阅读最新的文章,或者有技术问题需要交流和沟通,可搜索并关注微信公众号"希望睿智"。

相关推荐
倒头就睡的小比特1 天前
算法竞赛C++常用的STL
c++·算法
weilx12341 天前
C++笔记-文件IO-<fcntl.h>
c++
Smileyqp沛沛1 天前
前端?C++ ?较大差异基础罗列
c++·基础·前端转c++
C语言小火车1 天前
C/C++ 为什么需要编译器?
开发语言·c++
旖旎夜光1 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
吞下星星的少年·-·1 天前
C++ 萌新语法入门篇
c++·算法比赛
霍霍的袁1 天前
【C++】map 和 set 的使用 | 从用法到底层
开发语言·c++·学习·visual studio
another heaven1 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
程序猿编码1 天前
告别改源码适配模型:纯 C++ 可配置 LLM 推理引擎,全格式全结构兼容
c++·大模型·llm·推理引擎
此生决int1 天前
深入理解C++系列(20)——C++11(下)
开发语言·c++