You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让C++20的format_to_n在空间不足时保证字符串零终止?

解决fmt::format_to_n自动添加终止符的问题

首先,咱们先理清你当前代码的核心问题:你手动把'\0'作为参数传入格式字符串,但fmt::format_to_n的第二个参数是允许写入的最大字符数(不含终止符),所以当你传入长度2时,它会优先写入"42"而不是把'\0'放进去,导致最终缓冲区里没有正确的终止符,输出了42而非预期的4。

下面是无需手动比较写入长度的解决方案,核心是利用fmt::format_to_n的返回值来自动添加终止符:

实现思路

  1. 明确缓冲区总容量:调用函数时传入缓冲区的总大小(包括终止符的位置),这样我们可以提前预留一个位置给'\0'。
  2. 预留终止符位置调用format_to_n:给format_to_n的第二个参数传入缓冲区大小-1,确保不会占用终止符的位置。
  3. 自动追加终止符:fmt::format_to_n会返回一个包含out指针的结构体,这个指针指向最后一个写入字符的下一个位置,直接在这里写入'\0'即可——如果格式化内容超过预留长度,out会自动停在缓冲区大小-1的位置,写入'\0'刚好不会越界,完全不用手动判断写入长度。

修改后的代码

#include<string>
#include<iostream>
#define FMT_HEADER_ONLY
#include <fmt/format.h>

void f(char* in, size_t buf_total_size){
    // 预留一个位置给终止符,所以最大写入字符数是buf_total_size - 1
    auto fmt_result = fmt::format_to_n(in, buf_total_size - 1, "{}{}", 42, "");
    // 自动在写入的末尾添加终止符
    *fmt_result.out = '\0';
    std::cout << in;
}

int main(){
    char arr[]= "ABI"; // sizeof(arr)是4,包含默认的'\0'
    f(arr, sizeof(arr));
}

针对你的需求调整

如果你希望输出4而非42,只需要把缓冲区大小设为2(即只能容纳1个内容字符+1个终止符):

int main(){
    char arr[2]; // 缓冲区总大小2
    f(arr, sizeof(arr));
}

此时format_to_n最多写入1个字符('4'),然后在arr[1]的位置写入'\0',最终输出就是4。

额外说明

  • 不需要把'\0'作为格式参数传入,手动添加终止符更可靠,也避免了格式字符串的冗余。
  • 这种方式天然支持多参数格式化,不管你传入多少个参数,都会自动按总长度截断并添加终止符,完美解决你提到的多参数场景需求。

内容的提问来源于stack exchange,提问作者NoSenseEtAl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 19:47:41