C++ 格式化字符串:std::format 详解

在 C++20 中,标准库引入了 std::format 功能,这是一个强大的字符串格式化工具,它提供了类似 Python 的格式化语法,使得字符串格式化变得更加简单和直观。

基本用法

1. 简单格式化

#include <format>
#include <string>
#include <iostream>

int main() {
    std::string name = "Alice";
    int age = 25;
    
    // 基本格式化
    std::string result = std::format("My name is {} and I am {} years old", name, age);
    std::cout << result << std::endl;
    
    // 使用位置参数
    std::string result2 = std::format("I am {1} years old, my name is {0}", name, age);
    std::cout << result2 << std::endl;
    
    return 0;
}

2. 格式化选项

std::format支持丰富的格式化选项,可以满足各种格式化需求:

2.1 对齐选项

// 左对齐
std::format("{:<10}", "text");     // "text      "
std::format("{:*<10}", "text");    // "text******"

// 右对齐
std::format("{:>10}", "text");     // "      text"
std::format("{:0>10}", "42");      // "0000000042"

// 居中对齐
std::format("{:^10}", "text");     // "   text   "
std::format("{:*^10}", "text");    // "***text***"

2.2 符号选项

int num = 42;
double neg = -42.0;

// 显示正负号
std::format("{:+}", num);          // "+42"
std::format("{:+}", neg);          // "-42"
std::format("{:-}", num);          // "42"
std::format("{: }", num);          // " 42"(空格表示正数)

// 显示进制前缀
std::format("{:#x}", num);         // "0x2a"
std::format("{:#o}", num);         // "052"
std::format("{:#b}", num);         // "0b101010"

2.3 精度选项

double pi = 3.14159;
double large = 1234567.89;
double small = 0.00012345;

// 固定精度
std::format("{:.2f}", pi);         // "3.14"
std::format("{:.0f}", pi);         // "3"

// 科学计数法精度
std::format("{:.2e}", pi);         // "3.14e+00"
std::format("{:.2E}", pi);         // "3.14E+00"

// 通用格式精度(:g)
// 对于较小的数字,使用定点表示法
std::format("{:g}", pi);           // "3.14159"
std::format("{:.2g}", pi);         // "3.1"
std::format("{:.6g}", pi);         // "3.14159"

// 对于较大的数字,自动使用科学计数法
std::format("{:g}", large);        // "1.23457e+06"
std::format("{:.2g}", large);      // "1.2e+06"
std::format("{:.6g}", large);      // "1.23457e+06"

// 对于很小的数字,自动使用科学计数法
std::format("{:g}", small);        // "1.2345e-04"
std::format("{:.2g}", small);      // "1.2e-04"
std::format("{:.6g}", small);      // "1.2345e-04"

// 使用 # 标志强制显示小数点
std::format("{:#g}", pi);          // "3.14159"
std::format("{:#.2g}", pi);        // "3.1"
std::format("{:#.0g}", pi);        // "3."

// 使用 G 可以输出大写的 E
std::format("{:G}", large);        // "1.23457E+06"
std::format("{:.2G}", large);      // "1.2E+06"

:g格式说明符的特点:

  1. 自动选择最合适的表示方式:
    • 对于较小的数字,使用定点表示法
    • 对于较大的数字,使用科学计数法
    • 对于很小的数字,使用科学计数法
  2. 可以配合精度说明符使用(如.2g)
  3. 使用#标志可以强制显示小数点
  4. 使用G可以输出大写的E(科学计数法)
  5. 精度表示有效数字的位数,而不是小数位数

2.4 类型选项

int num = 42;
char ch = 'A';
bool flag = true;

// 整数类型
std::format("{:d}", num);          // "42"(十进制)
std::format("{:x}", num);          // "2a"(十六进制小写)
std::format("{:X}", num);          // "2A"(十六进制大写)
std::format("{:o}", num);          // "52"(八进制)
std::format("{:b}", num);          // "101010"(二进制)

// 字符和布尔值
std::format("{:c}", ch);           // "A"
std::format("{:b}", flag);         // "true"

2.5 本地化选项

#include <locale>

double price = 1234.56;

// 使用本地化格式
std::locale::global(std::locale("zh_CN.UTF-8"));
std::format("{:L}", price);        // "1,234.56"

// 货币格式
std::format("{:L}", std::money_put<char>(), price);  // "¥1,234.56"

2.6 组合选项

int num = 42;

// 组合多个选项
std::format("{:+0>10}", num);      // "+000000042"
std::format("{:#0>10x}", num);     // "0x0000002a"
std::format("{:0>+#10}", num);     // "+000000042"

高级用法

1. 自定义类型格式化

struct Point {
    int x, y;
};

template<>
struct std::formatter<Point> {
    constexpr auto parse(std::format_parse_context& ctx) {
        return ctx.begin();
    }
    
    auto format(const Point& p, std::format_context& ctx) {
        return std::format_to(ctx.out(), "({}, {})", p.x, p.y);
    }
};

// 使用
Point p{10, 20};
std::string result = std::format("Point: {}", p);  // "Point: (10, 20)"

2. 性能优化

// 预分配缓冲区
std::string buffer;
buffer.reserve(100);
std::format_to(std::back_inserter(buffer), "Value: {}", 42);

// 直接输出到流
std::format_to(std::ostream_iterator<char>(std::cout), "Value: {}", 42);

注意事项

  1. std::format是 C++20 的特性,需要确保编译器支持
  2. 使用前需要包含<format>头文件
  3. 格式化字符串中的占位符{}数量必须与参数数量匹配
  4. 格式化选项的语法为{:选项},其中选项是可选的
  5. 注意处理异常情况,如格式化失败

链接:https://juejin.cn/post/7507454126605156363

- 本文内容来自网络,如有侵权,请联系本站处理。

11-26   阅读(5)   评论(0)
 标签: 编程 cpp

涨知识
面向对象编程

面向对象编程(Object Oriented Programming)是一种编程方法,其本质是以建立模型体现出来的抽象思维过程和面向对象的方法。

评论:
相关文章
Arduino 数据结构: 队列Queue

Queue 库提供了一个通用的 C++ 动态队列实现,专为在 Arduino 项目中使用而定制。


Arduino 数据结构: ArrayList

ArrayList 类是一个 C++ 模板类,它提供了 ArrayList 的实现,以便轻松存储任何指定类型的值。它允许使用索引进行高效存储和检索,支持排序操作。