std::string 格式化,如 sprintf

新手上路,请多包涵

我必须用 --- 格式化 std::string sprintf 并将其发送到文件流中。我怎样才能做到这一点?

原文由 Max Frai 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.5k
2 个回答

您不能直接执行此操作,因为您没有对底层缓冲区的写访问权(直到 C++11;请参阅 Dietrich Epp 的 评论)。您必须首先在 c-string 中执行此操作,然后将其复制到 std::string 中:

   char buff[100];
  snprintf(buff, sizeof(buff), "%s", "Hello");
  std::string buffAsStdStr = buff;

但我不确定你为什么不只使用字符串流?我假设您有特定的理由不只是这样做:

   std::ostringstream stringStream;
  stringStream << "Hello";
  std::string copyOfStr = stringStream.str();

原文由 Doug T. 发布,翻译遵循 CC BY-SA 3.0 许可协议

C++17 解决方案(这将适用于 std::string 和 std::wstring):

分配缓冲区,格式化到其中并在将其复制到另一个字符串之后效率不高。可以直接在该字符串缓冲区中以格式化字符串 & 格式的大小创建 std::string:

 #include <string>
#include <stdexcept>
#include <cwchar>
#include <cstdio>
#include <type_traits>

template<typename T, typename ... Args>
std::basic_string<T> string_format(T const* const format, Args ... args)
{
    int size_signed{ 0 };

    // 1) Determine size with error handling:
    if constexpr (std::is_same_v<T, char>) { // C++17
        size_signed = std::snprintf(nullptr, 0, format, args ...);
    }
    else {
        size_signed = std::swprintf(nullptr, 0, format, args ...);
    }
    if (size_signed <= 0) {
        throw std::runtime_error("error during formatting.");
    }
    const auto size = static_cast<size_t>(size_signed);

    // 2) Prepare formatted string:
    std::basic_string<T> formatted(size, T{});
    if constexpr (std::is_same_v<T, char>) { // C++17
        std::snprintf(formatted.data(), size + 1, format, args ...); // +1 for the '\0' (it will not be part of formatted).
    }
    else {
        std::swprintf(formatted.data(), size + 1, format, args ...); // +1 for the '\0' (it will not be part of formatted).
    }

    return formatted; // Named Return Value Optimization (NRVO), avoids an unnecessary copy.
}

另外:通常,格式参数是 char[] / wchar_t[] & 创建 std::string 对象效率不高。传递 char* 或 wchar_t* & 如果你已经有一个 std::string 对象,你仍然可以将它用作 your_string.c_str()。例子:

 int main()
{
    int i{ 0 };

    // The format parameter is a char[] / wchar_t[]:

    const std::string title1 = string_format("story[%d].", ++i); // => "story[1]"

    const std::wstring title2 = string_format(L"story[%d].", ++i); // => L"story[2]"

    // If you already have a std::string object:

    const std::string format1{ "story[%d]." };
    const std::string title3 = string_format(format1.c_str(), ++i); // => "story[3]"

    const std::wstring format2{ L"story[%d]." };
    const std::wstring title4 = string_format(format2.c_str(), ++i); // => L"story[4]"
}

原文由 Amit 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题