如何使用fmtlib保留多行字符串的缩进格式?
使用fmtlib为多行字符串添加统一缩进的解决方案
问题场景
你在使用fmtlib格式化自动生成代码时,遇到了多行字符串参数无法继承格式字符串中指定缩进的问题。示例代码如下:
auto str = fmt::format( "{header}\n" " {body}\n" "{footer}", fmt::var("header", single_line_str()), fmt::var("body", multi_line_str()), fmt::var("footer", single_line_str()) );
当body为以下多行内容时:
The quick brown fox jumped over the lazy dog
实际输出仅第一行带有缩进:
begin The quick brown fox jumped over the lazy dog end
但你需要body的每一行都自动带上格式字符串中指定的 缩进,同时嵌套场景下支持相对缩进(而非硬编码绝对缩进)。
解决方案
可以通过自定义辅助函数或fmtlib格式化器实现,以下是两种实用方案:
方案1:直接使用辅助函数处理多行字符串
定义一个工具函数,给多行字符串的每一行(除第一行外)添加指定缩进:
#include <sstream> #include <string> std::string indent_multiline(const std::string& input, const std::string& indent) { std::ostringstream oss; std::istringstream iss(input); std::string line; bool is_first_line = true; while (std::getline(iss, line)) { if (!is_first_line) { oss << '\n' << indent; } oss << line; is_first_line = false; } return oss.str(); }
修改原代码,在传入body参数时调用该函数:
auto str = fmt::format( "{header}\n" " {body}\n" "{footer}", fmt::var("header", single_line_str()), fmt::var("body", indent_multiline(multi_line_str(), " ")), fmt::var("footer", single_line_str()) );
方案2:自定义fmtlib格式化器(更适合嵌套场景)
如果需要频繁处理这类多行缩进需求,或要支持灵活的嵌套相对缩进,可以定义一个包装结构体并实现fmt格式化器:
#include <fmt/core.h> #include <sstream> #include <string> // 包装多行字符串和对应的缩进 struct indented_multiline { std::string content; std::string indent; }; // 为indented_multiline实现fmt格式化逻辑 template <> struct fmt::formatter<indented_multiline> : fmt::formatter<std::string> { template <typename FormatContext> auto format(const indented_multiline& im, FormatContext& ctx) { std::ostringstream oss; std::istringstream iss(im.content); std::string line; bool is_first_line = true; while (std::getline(iss, line)) { if (!is_first_line) { oss << '\n' << im.indent; } oss << line; is_first_line = false; } return fmt::formatter<std::string>::format(oss.str(), ctx); } };
使用时直接传递包装后的对象,嵌套场景下只需传递对应层级的缩进即可:
// 外层缩进 auto outer_str = fmt::format( "{header}\n" " {}\n" "{footer}", single_line_str(), indented_multiline{multi_line_str(), " "}, single_line_str() ); // 嵌套场景:内层在基础缩进上再加两个空格 auto nested_str = fmt::format( "outer_begin\n" " {}\n" "outer_end", indented_multiline{get_nested_multi_line_str(), " "} );
内容的提问来源于stack exchange,提问作者Jonah F
相关产品推荐
相关产品推荐

