强制 format_to_n 使用终止零

Posted

技术标签:

【中文标题】强制 format_to_n 使用终止零【英文标题】:Forcing format_to_n to use terminating zero 【发布时间】:2020-02-28 10:50:38 【问题描述】:

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

我正在寻找的是确保在我的空间用完时我的字符串仍然为零终止的方法。 例如,我希望下面的程序输出 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,'\0');
    std::cout << in;


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

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

如果你想知道为什么我使用 '\0' 作为参数:

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

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

【问题讨论】:

保存format_to_n的返回值并使用out迭代器将最后一个字节设置为零怎么样? 【参考方案1】:

format_to_n 返回一个结果。您可以使用该结构:

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

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

【讨论】:

nitpikc:我会使用 _ 而不是 size,但这是一种风格。【参考方案2】:

format_to_n 返回一个结构,其中包含最后一个写入字符之后的迭代器。因此,很容易根据最大字符数检查该迭代器和原始迭代器之间的差异,并在适当的地方插入 \0

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 = '\0';

  std::cout << in;

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

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

【讨论】:

*fmt::format_to_n(in, max_chars - 1, "", 42).out = '\0'; 这样的oneliner 会起作用吗?它是max_chars - 1,所以它最多写1个字符,out应该指向末尾。

以上是关于强制 format_to_n 使用终止零的主要内容,如果未能解决你的问题,请参考以下文章

使用 opsworks nginx 和 ELB 终止 SSL 时强制使用 HTTPS

进程被强制终止时的进程退出代码

强制终止 WIA 或 TWAIN 驱动程序(扫描仪)

使用yum时用Ctrl+C强制终止出现的Error: rpmdb open failed解决方案

使用yum时用Ctrl+C强制终止出现的Error: rpmdb open failed解决方案

使用yum时用Ctrl+C强制终止出现的Error: rpmdb open failed解决方案