像C11标准中的Boost.Format这样的东西吗?我已经能够避免使用Boost,而有了一个更好的C11选项来满足我的所有其他需求。就此而言,Boost.Format无法与Python format()的语法相提并论,类似的语法甚至会更好。
format()
9w11ddsr1#
C11、14和17没有提供类似的功能。然而,C20提供了std::format,它在本质上类似于Boost Format,但设计允许更有效的实现。{fmt} library是这种格式化工具的实现,它只需要C++11:
std::format
std::string s = fmt::format("I'd rather be {1} than {0}.", "right", "happy");
knsnq2tg2#
有一个类似于 boost-format 的建议,但是它既不是C11也不是C14的一部分,也没有添加任何与字符串格式化相关的内容。在这里你可以找到最新的提案。与 boost-format 不同的是,它是基于变量模板的。
rta7y2nd3#
用c++11正则表达式和变量模板实现的类Python格式字符串函数。
/** Helper code to unpack variadic arguments */ namespace internal { template<typename T> void unpack(std::vector<std::string> &vbuf, T t) { std::stringstream buf; buf << t; vbuf.push_back(buf.str()); } template<typename T, typename ...Args> void unpack(std::vector<std::string> &vbuf, T t, Args &&... args) { std::stringstream buf; buf << t; vbuf.push_back(buf.str()); unpack(vbuf, std::forward<Args>(args)...); } } /** Python-like string formatting */ template<typename ... Args> std::string format(const std::string& fmt, Args ... args) { std::vector<std::string> vbuf; // store arguments as strings std::string in(fmt), out; // unformatted and formatted strings std::regex re_arg("\\{\\b\\d+\\b\\}"); // search for {0}, {1}, ... std::regex re_idx("\\b\\d+\\b"); // search for 0, 1, ... std::smatch m_arg, m_idx; // store matches size_t idx = 0; // index of argument inside {...} // Unpack arguments and store them in vbuf internal::unpack(vbuf, std::forward<Args>(args)...); // Replace all {x} with vbuf[x] while (std::regex_search(in, m_arg, re_arg)) { out += m_arg.prefix(); auto text = m_arg[0].str(); if (std::regex_search(text, m_idx, re_idx)) { idx = std::stoi(m_idx[0].str()); } if(idx < vbuf.size()) { out += std::regex_replace(m_arg[0].str(), re_arg, vbuf[idx]); } in = m_arg.suffix(); } out += in; return out; }
示例:cpp.sh/9cvtz
kuhbmx9i4#
std::string
interactive version
#include <iostream> #include <string> #include <stdio.h> #include <assert.h> template<typename... Args> std::string fmt_str(std::string fmt, Args... args) { size_t bufferSize = 1000; char *buffer = new char[bufferSize]; int n = sprintf(buffer, fmt.c_str(), args...); assert (n >= 0 and n < (int) bufferSize - 1 && "check fmt_str output"); std::string fmtStr (buffer); delete buffer; return fmtStr; } int main() { int a=1, b=2; double c=3.; std::cout << fmt_str("%d plus %d is %f", a, b, c) << std::endl; return 0; }
输出
5ssjco0h5#
template<typename... Args> std::string fmt_str(const std::string& fmt, Args... args) { static const int bufferSize = 1000; char buffer[bufferSize]; int n = snprintf(buffer, bufferSize, fmt.c_str(), args...); assert(n >= 0 and n <= bufferSize - 1 && "check fmt_str output"); return (buffer); }
//基于Markus的一些改进:将输入更改为ref,缓冲区避免新建,使用snprintf避免缓冲区溢出,直接返回以避免复制构造函数。//它应该是Markus Dutschke的注解,而不是答案,但是注解字段不能很好地格式化代码段,我在这里提取代码。
5条答案
按热度按时间9w11ddsr1#
C11、14和17没有提供类似的功能。
然而,C20提供了
std::format
,它在本质上类似于Boost Format,但设计允许更有效的实现。{fmt} library是这种格式化工具的实现,它只需要C++11:knsnq2tg2#
有一个类似于 boost-format 的建议,但是它既不是C11也不是C14的一部分,也没有添加任何与字符串格式化相关的内容。
在这里你可以找到最新的提案。与 boost-format 不同的是,它是基于变量模板的。
rta7y2nd3#
用c++11正则表达式和变量模板实现的类Python格式字符串函数。
示例:cpp.sh/9cvtz
kuhbmx9i4#
使用sprintf
std::string
,请使用以下代码段最小重现性示例:使用printf语法格式化
std::string
interactive version
输出
5ssjco0h5#
//基于Markus的一些改进:将输入更改为ref,缓冲区避免新建,使用snprintf避免缓冲区溢出,直接返回以避免复制构造函数。
//它应该是Markus Dutschke的注解,而不是答案,但是注解字段不能很好地格式化代码段,我在这里提取代码。