【问题标题】:What is the correct way to use fmt::sprintf?使用 fmt::sprintf 的正确方法是什么?
【发布时间】:2021-12-30 12:32:51
【问题描述】:

我正在尝试优化我的软件,为此我需要改变我存储和绘制事物的方式。

很多人说 fmt 在做这些事情上比 iostream 快得多,但我坐在这里试图了解我做错了什么。

旧代码正在运行:

auto type = actor->GetName();
char name[0x64];
if (type.find("AI") != std::string::npos)
sprintf(name, "AI [%dm]", dist);

新的不是:

auto type = actor->GetName();
char name[0x64];
if (type.find("AI") != std::string::npos)
fmt::sprintf("AI [%dm]", dist);

我做错了什么?

【问题讨论】:

  • Sooo 你认为fmt::sprintf 将其输出存储在哪里? char name[0x20]sprintf 上面做什么?以及为什么不使用fmt::format的任何具体原因?
  • fmt::sprintf 不将输出缓冲区作为参数,而是返回std::string。尝试使用该返回值。
  • 你仍然没有使用你对fmt::sprintf的调用的返回值。
  • 除非您确实执行大量格式化 I/O(您不应该这样做),否则任何一个版本的性能都无关紧要。
  • 阅读 fmt 的文档以了解如何使用函数。

标签: c++ fmt


【解决方案1】:

正如 cmets 中提到的 @NathanPiersonfmt::sprintf() 返回一个 std::string,您将忽略它。 fmt::sprintf() 不会填充 char[] 缓冲区(并不是说您无论如何都要向其中传递一个,就像您使用 ::sprintf() 一样)。

改变这个:

char name[0x64];
fmt::sprintf("AI [%dm]", dist);

到这里:

std::string name = fmt::sprintf("AI [%dm]", dist);

然后您可以根据需要使用name。如果您需要将其传递给需要 (const) char* 的函数,您可以为此使用 name.c_str()name.data()

【讨论】:

    【解决方案2】:

    很多人说 fmt 在做这些事情方面比 iostream,但我坐在这里试图了解我做错了什么。

    除了 Remy Lebeau 的正确答案之外,还有一点。你提到速度是一个考虑因素。在这种情况下,您可能希望避免构造std::string,并使用fmt::format_to_n()(或std::format_to_n)直接格式化到您的字符缓冲区:

    auto type = actor->GetName();
    char name[0x64];
    if (type.find("AI") != std::string::npos) {
        fmt::format_to_n(name, 0x64, "AI [{}m]", dist);
    }
    

    不幸的是,我认为fmt 没有针对现有缓冲区的函数并且使用 printf 格式说明符。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-24
      • 2021-09-23
      • 2017-04-07
      • 2013-01-09
      • 2013-03-19
      • 2019-05-11
      • 2018-02-17
      相关资源
      最近更新 更多