强制 format_to_n 使用终止零

Forcing format_to_n to use terminating zero

除了最常见的(格式)函数外,C++20 还带有 format_to_n,它接受输出迭代器和计数。

我正在寻找的是确保万一 运行 超出 space 我的字符串仍然以零终止的方法。 例如我希望下面的程序输出 4 而不是 42.

#include<string>
#include<iostream>
#define FMT_HEADER_ONLY 
#include <fmt/format.h>
void f(char* in){
    fmt::format_to_n(in, 2,"{}{}", 42,'[=11=]');
    std::cout << in;
}

int main(){
    char arr[]= "ABI";
    f(arr);
}

如果我不手动比较写入的字符数和我提供给函数的最大长度,这可能吗?

如果您想知道我为什么使用“\0”作为参数:

我不知道如何将终止字符放入格式字符串中。

注意:我知道对于一个参数,我可以用 : 指定最大长度。但我想要一个适用于多个参数的解决方案。

format_to_n returns 一个结构,除其他外,包含经过最后一个写入字符的迭代器。因此,很容易简单地检查该迭代器与原始迭代器之间的最大字符数差异,并在适当的地方插入一个 [=12=]

void f(char* in)
{
  const max_chars = 2;
  auto fmt_ret = fmt::format_to_n(in, max_chars,"{}", 42);
  char *last = fmt_ret.out;
  if(last - in == max_chars)
    --last;
  *last = '[=10=]';

  std::cout << in;
}

请注意,这假定数组仅包含您尝试传递给 format_to_n 的字符数(包括 NUL 终止符)。因此,上面的代码将覆盖最后一个用 NUL 终止符写入的字符,实质上是进一步截断。

如果您将数组中的字符数 - 1 传递给 format_to_n,那么您总是可以简单地将 NUL 终止符写入 fmt_ret.out 本身。

format_to_nreturns一个结果。您可以使用该结构:

void f(char* in){
    auto [out, size] = fmt::format_to_n(in, 2, "{}", 42);
    *out = '[=10=]';
    std::cout << in;
}

请注意,这可能会将 "42[=12=]" 写入 in,因此请适当调整您的容量(2 对于大小为 3 的缓冲区是正确的)。