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

如何使用fmt库控制嵌套容器(如二维vector)的格式与分隔符?

控制fmt库中嵌套容器的分隔符

基础回顾

  • 打印普通范围容器:
#include <fmt/ranges.h>

std::vector<int> t = {1, 2, 3};
// 输出 "[1, 2, 3]"
fmt::print("{}", t);
  • 自定义顶层容器的分隔符:
// 输出 "1| 2| 3"
fmt::print("{}", fmt::join(t, "| "));

嵌套容器的问题

当处理嵌套容器(如std::vector<std::vector<int>>)时,直接使用fmt::join只能控制顶层元素的分隔符。例如执行以下代码:

std::vector<std::vector<int>> v = {{1,2,3}, {4,5,6}, {7,8,9}};
fmt::print("{}", fmt::join(v, "| "));

会输出 [1, 2, 3]| [4, 5, 6]| [7, 8, 9],无法修改内层容器的默认分隔符。

解决方案

方法1:为内层容器自定义格式化器

通过为特定类型的内层容器定制fmt::formatter,可以修改其默认的分隔符:

#include <fmt/ranges.h>
#include <vector>

// 为std::vector<int>定制格式化器,指定内层分隔符为"; "
template <> struct fmt::formatter<std::vector<int>> : fmt::formatter<fmt::format_string<int>> {
  template <typename FormatContext>
  auto format(const std::vector<int>& v, FormatContext& ctx) const {
    return fmt::format_to(ctx.out(), "{}", fmt::join(v, "; "));
  }
};

int main() {
  std::vector<std::vector<int>> v = {{1,2,3}, {4,5,6}, {7,8,9}};
  // 顶层用" | "分隔,内层用"; "分隔
  fmt::print("{}", fmt::join(v, " | "));
  // 输出:1; 2; 3 | 4; 5; 6 | 7; 8; 9
}

方法2:递归处理任意深度的嵌套容器

如果需要支持任意层级的嵌套容器,可以编写递归函数来动态控制各层级的分隔符:

#include <fmt/ranges.h>
#include <vector>
#include <type_traits>

// 简化判断:是否为可遍历的范围容器
template <typename T>
concept is_range = requires(T t) {
  std::begin(t);
  std::end(t);
};

// 处理非容器类型的元素
template <typename T>
requires (!is_range<T>)
void format_element(const T& elem, fmt::format_context& ctx) {
  fmt::format_to(ctx.out(), "{}", elem);
}

// 递归处理容器类型,可通过层级参数调整分隔符
template <is_range T>
void format_element(const T& range, fmt::format_context& ctx, int level = 0) {
  auto it = std::begin(range);
  auto end_it = std::end(range);
  if (it == end_it) return;

  format_element(*it, ctx, level + 1);
  ++it;
  
  // 根据当前层级选择分隔符:层级1(顶层)用" | ",层级2(内层)用", "
  const char* sep = (level == 0) ? " | " : ", ";
  for (; it != end_it; ++it) {
    fmt::format_to(ctx.out(), "{}", sep);
    format_element(*it, ctx, level + 1);
  }
}

// 包装函数,返回格式化后的字符串
template <is_range T>
std::string format_nested(const T& range) {
  std::string result;
  fmt::format_context ctx{result};
  format_element(range, ctx);
  return result;
}

int main() {
  std::vector<std::vector<int>> v = {{1,2,3}, {4,5,6}, {7,8,9}};
  fmt::print("{}", format_nested(v));
  // 输出:1, 2, 3 | 4, 5, 6 | 7, 8, 9
}

这种递归方式可以轻松扩展到更深的嵌套结构,只需调整sep的判断逻辑即可为不同层级设置不同分隔符。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 07:20:17