You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从fmt::format格式字符串中提取width参数?

Extract Width Parameter from fmt Format String

Problem Description

我需要一种方法从fmt::format的格式字符串中提取width参数,而不是获取格式化操作后的结果大小(后者可以通过auto size = fmt::formatted_size("{:>5.2f}", 13453453.76345f);轻松实现)。

例如,对于fmt::format("{:>5.2f}", 13.23454f);,希望提取其中的数字5;同时该方法需要支持整数格式字符串,比如fmt::format("{:>4d}", 42);,提取其中的数字4。期望能有类似auto width = get_format_width("{:>5.2f}"); assert(width == 5);的实现方式。

Solution

fmt库本身提供了用于解析格式说明符的底层API,我们可以利用这些API来精准提取width参数,避免自己编写容易出错的字符串解析逻辑。下面是一个可直接使用的实现:

#include <fmt/core.h>
#include <fmt/format.h>
#include <optional>
#include <string_view>
#include <cassert>
#include <cctype>

std::optional<int> get_format_width(std::string_view format_str) {
    // 定位格式说明符的起始标记':'
    const size_t colon_pos = format_str.find(':');
    if (colon_pos == std::string_view::npos) {
        // 格式字符串中没有指定格式说明符,无width参数
        return std::nullopt;
    }

    // 提取从':'到'}'之间的格式说明内容
    std::string_view spec_part = format_str.substr(colon_pos + 1);
    const size_t closing_brace = spec_part.find('}');
    if (closing_brace != std::string_view::npos) {
        spec_part = spec_part.substr(0, closing_brace);
    }

    // 使用fmt的解析上下文处理格式说明
    fmt::format_parse_context parse_ctx(spec_part);
    auto spec_it = parse_ctx.begin();

    // 跳过格式说明中的前缀字符(对齐、符号、标记等)
    while (spec_it != parse_ctx.end() && (
        *spec_it == '<' || *spec_it == '>' || *spec_it == '^' || // 对齐符
        *spec_it == '+' || *spec_it == '-' || *spec_it == ' ' || // 符号标记
        *spec_it == '#' // 替代格式标记
    )) {
        ++spec_it;
    }

    // 解析连续的数字作为width参数
    if (spec_it != parse_ctx.end() && std::isdigit(static_cast<unsigned char>(*spec_it))) {
        int width_value = 0;
        while (spec_it != parse_ctx.end() && std::isdigit(static_cast<unsigned char>(*spec_it))) {
            width_value = width_value * 10 + (*spec_it - '0');
            ++spec_it;
        }
        return width_value;
    }

    // 未找到固定数值的width参数
    return std::nullopt;
}

// 测试示例
int main() {
    // 浮点数格式测试
    assert(get_format_width("{:>5.2f}") == 5);
    // 整数格式测试
    assert(get_format_width("{:>4d}") == 4);
    // 无width参数的情况
    assert(!get_format_width("{:.2f}").has_value());
    // 无格式说明符的情况
    assert(!get_format_width("{}").has_value());
    // 带符号和对齐的复杂格式
    assert(get_format_width("{:+<6d}") == 6);

    return 0;
}

How It Works

  1. 定位格式说明符:先找到格式字符串中的:标记,确定格式说明部分的起始位置
  2. 提取格式说明内容:截取从:到}之间的字符串,这就是我们需要解析的格式规则部分
  3. 跳过前缀字符:格式说明中可能包含对齐符(>、<、^)、符号标记(+、-、 )等前缀,我们需要先跳过这些字符,找到width参数的起始位置
  4. 解析width数值:读取连续的数字字符,转换为整数,这就是我们要提取的width参数
  5. 边界情况处理:如果没有格式说明符、没有固定数值的width参数,都会返回std::nullopt

Notes

  • 这个实现不支持动态width参数(比如{:*>{}}这种使用其他参数作为width的情况),因为这类width不是固定在格式字符串中的数值
  • 代码适配fmt 7.x及以上版本,确保编译时链接对应版本的fmt库

内容的提问来源于stack exchange,提问作者user23573

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 13:37:35