在C++11标准中有像Boost.Format这样的东西吗?对于我所遇到的所有其他需求,我都能够避免使用Boost并选择更好的C++11选项。
说到这一点,Boost.Format与Python的format()
语法相比不能相提并论。类似于这样的东西将更加优秀。
在C++11标准中有像Boost.Format这样的东西吗?对于我所遇到的所有其他需求,我都能够避免使用Boost并选择更好的C++11选项。
说到这一点,Boost.Format与Python的format()
语法相比不能相提并论。类似于这样的东西将更加优秀。
std::format
,它在精神上类似于Boost Format,但设计允许更有效的实现。{fmt}库是这种格式化工具的实现,它只需要C++11。std::string s = fmt::format("I'd rather be {1} than {0}.", "right", "happy");
免责声明:我是{fmt}和C++20 std::format的作者。
/**
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;
}
regex_search
不再允许使用临时字符串,所以在调用regex_search
之前添加这个:auto tmp = m_arg[0].str();
并将tmp
作为第一个参数传递。 - galariustemplate<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的一些小改进:将输入更改为引用,避免缓冲区新建,使用snprintf避免缓冲区溢出,直接返回以避免复制构造函数。在我的项目中使用它
//这应该是对Markus Dutschke的评论,而不是答案,但是评论字段无法很好地格式化代码片段,因此我在此提取了代码。
std::string
,请使用以下代码片段最小可复现示例:使用printf语法格式化std::string
#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;
}
输出
1 plus 2 is 3.000000
.c_str()
。另外,它远不如Python的format()
好用。 - Chris Redford