如何让C++20的format_to_n在空间不足时保证字符串零终止?
解决fmt::format_to_n自动添加终止符的问题
首先,咱们先理清你当前代码的核心问题:你手动把'\0'作为参数传入格式字符串,但fmt::format_to_n的第二个参数是允许写入的最大字符数(不含终止符),所以当你传入长度2时,它会优先写入"42"而不是把'\0'放进去,导致最终缓冲区里没有正确的终止符,输出了42而非预期的4。
下面是无需手动比较写入长度的解决方案,核心是利用fmt::format_to_n的返回值来自动添加终止符:
实现思路
- 明确缓冲区总容量:调用函数时传入缓冲区的总大小(包括终止符的位置),这样我们可以提前预留一个位置给
'\0'。 - 预留终止符位置调用format_to_n:给
format_to_n的第二个参数传入缓冲区大小-1,确保不会占用终止符的位置。 - 自动追加终止符:
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
相关产品推荐
相关产品推荐

