23

像 C++11 标准中的 Boost.Format 之类的东西吗?我已经能够避免使用具有更好 C++11 选项的 Boost 来满足我所拥有的所有其他需求。

就此而言,Boost.Format 与 Python 的语法并无二致format()。像这样的东西会更好。

4

4 回答 4

27

C++11、14 和 17 不提供类似的东西。

然而,C++20 提供了std::format与 Boost 格式类似的精神,但其设计允许更有效的实现。{fmt} 库是这个格式化工具的一个实现,它只需要 C++11:

std::string s = fmt::format("I'd rather be {1} than {0}.", "right", "happy");

免责声明:我是 {fmt} 和 C++20 std::format 的作者

于 2014-10-08T21:34:57.703 回答
7

有一个类似于boost-format的提案。但是,它既不是 C++11 也不是 C++14 的一部分,也没有添加任何与字符串格式相关的内容。

在这里您可以找到最新的提案。与boost-format相比,它基于可变参数模板。

于 2014-05-01T17:57:38.397 回答
2

使用 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

于 2017-06-17T18:50:39.190 回答
0

使用 sprintf

  • 对于 C++20,使用std::format
  • 有来自版本 C++11的fmt 库
  • 格式化输出的一些简单解决方案是printf
  • 要使用 printf 语法编写 a std::string,请使用以下代码段

最小可重现示例:std::string使用 printf 语法的格式

互动版

#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
于 2020-09-10T07:23:40.950 回答