我在C++工作.
我想用sprintf编写一个可能很长的格式化字符串(特别是像_snprintf_s这样的安全计数版本,但想法是一样的).在编译时大致的长度是未知的,所以我将不得不使用一些动态分配的内存而不是依赖一个大的静态缓冲区.有没有办法确定特定sprintf调用需要多少个字符,所以我总能确定我有足够大的缓冲区?
我的后备是我只需要格式字符串的长度,加倍它,并尝试.如果它工作,很好,如果不是,我只会加倍缓冲区的大小,然后再试一次.重复直到它适合.不完全是最聪明的解决方案.
看起来C99支持将NULL传递给snprintf来获取长度.我想我可以创建一个模块来包装该功能,如果没有别的,但我对这个想法不是很疯狂.
也许对"/ dev/null"/"nul"的fprintf可能会起作用吗?还有其他想法吗?
编辑:或者,是否有任何方法可以"spunk"sprintf所以它在中间写入?如果可能的话,它可以填充缓冲区,处理它,然后从它停止的地方开始重新填充.
手册页snprintf
说:
Return value Upon successful return, these functions return the number of characters printed (not including the trailing '\0' used to end output to strings). The functions snprintf and vsnprintf do not write more than size bytes (including the trailing '\0'). If the output was truncated due to this limit then the return value is the number of characters (not including the trailing '\0') which would have been written to the final string if enough space had been available. Thus, a return value of size or more means that the output was truncated. (See also below under NOTES.) If an output error is encountered, a negative value is returned.
这意味着您可以调用snprintf
大小为0.什么都不会被写入,返回值将告诉您需要为字符串分配多少空间:
int how_much_space = snprintf(NULL, 0, fmt_string, param0, param1, ...);
正如其他人所提到的,snprintf()
将返回缓冲区中所需的字符数,以防止输出被截断.您可以使用0缓冲区长度参数调用它来获取所需的大小,然后使用适当大小的缓冲区.
为了略微提高效率,可以使用一个足够大的缓冲区来调用它,snprintf()
如果输出被截断的话,只需要进行第二次调用.为了确保缓冲区在这种情况下正确释放,我经常会使用一个auto_buffer<>
为我处理动态内存的对象(并且在堆栈上有默认缓冲区以避免在正常情况下分配堆) .
如果您正在使用Microsoft编译器,则MS具有非标准_snprintf()
,其具有严重限制,即不总是空终止缓冲区并且不指示缓冲区应该有多大.
为了解决微软的不支持问题,我使用了snprintf()
Holger Weiss 的近公共域名.
当然,如果缺少非MS C或C++编译器snprintf()
,上述链接中的代码也应该可以正常工作.