如何使用标准库函数(非外部fmt库)创建含std::vector<std::string>参数的格式化字符串
使用C++标准库基于字符串向量创建格式化字符串
你的示例代码无法编译,核心原因是std::make_format_args是变参模板函数,要求直接传入单个格式化参数而非迭代器范围;同时C++标准库的std::format系列函数依赖编译时确定的参数数量,无法直接适配运行时动态大小的std::vector<std::string>。
下面分两种场景给出可行实现:
场景1:编译时已知参数数量
如果字符串向量的大小是编译时固定的,可以借助模板索引序列展开向量元素,适配std::vformat的要求:
#include <format> #include <vector> #include <string> #include <utility> #include <stdexcept> namespace detail { template<std::size_t... Indices> std::string format_impl(const std::string& fmt, const std::vector<std::string>& args, std::index_sequence<Indices...>) { return std::vformat(fmt, std::make_format_args(args[Indices]...)); } } // 模板参数N指定编译时确定的参数数量 template<std::size_t N> std::string format_fixed(const std::string& fmt, const std::vector<std::string>& args) { if (args.size() != N) { throw std::invalid_argument("参数数量与预期不匹配"); } return detail::format_impl(fmt, args, std::make_index_sequence<N>()); } // 使用示例 int main() { std::vector<std::string> args = {"Alice", "Bob"}; std::string result = format_fixed<2>("你好,{} 和 {}!", args); // result 为 "你好,Alice 和 Bob!" return 0; }
场景2:运行时动态参数数量
如果参数数量是运行时不确定的,需要手动解析格式字符串,替换{0}、{1}这类占位符,同时处理转义的{{}}:
#include <string> #include <vector> #include <cstddef> #include <stdexcept> #include <algorithm> std::string format(const std::string& fmt, const std::vector<std::string>& args) { std::string result; std::size_t pos = 0; const std::size_t fmt_len = fmt.size(); while (pos < fmt_len) { // 查找下一个左大括号 std::size_t open_brace = fmt.find('{', pos); if (open_brace == std::string::npos) { result += fmt.substr(pos); break; } // 追加左大括号之前的内容 result += fmt.substr(pos, open_brace - pos); // 处理转义的{{ if (open_brace + 1 < fmt_len && fmt[open_brace + 1] == '{') { result += '{'; pos = open_brace + 2; continue; } // 查找对应的右大括号 std::size_t close_brace = fmt.find('}', open_brace); if (close_brace == std::string::npos) { // 格式字符串不合法,追加剩余内容 result += fmt.substr(open_brace); break; } // 解析占位符索引 std::string index_str = fmt.substr(open_brace + 1, close_brace - open_brace - 1); try { std::size_t index = std::stoull(index_str); if (index < args.size()) { result += args[index]; } else { // 索引超出范围,保留原占位符 result += fmt.substr(open_brace, close_brace - open_brace + 1); } } catch (...) { // 索引不是合法数字,保留原占位符 result += fmt.substr(open_brace, close_brace - open_brace + 1); } pos = close_brace + 1; } return result; } // 使用示例 int main() { std::vector<std::string> args = {"苹果", "香蕉", "橙子"}; std::string result = format("我喜欢的水果:{0}、{1}、{2}", args); // result 为 "我喜欢的水果:苹果、香蕉、橙子" return 0; }
内容的提问来源于stack exchange,提问作者Dess
相关产品推荐
相关产品推荐

