目标:将数据序列化为JSON格式。
问题:我不能事先知道整数有多少个字符长。
我认为一个很好的方法是使用sprintf()
size_t length = sprintf(no_buff, "{data:%d}",12312);
char *buff = malloc(length);
snprintf(buff, length, "{data:%d}",12312);
//buff is passed on ...
字符串
当然,我可以使用像char a[256]
这样的堆栈变量来代替no_buff
。
**问题:**但是在C中是否有一个像unix /dev/null
这样的一次性写入的实用程序?Smth如下:
#define FORGET_ABOUT_THIS ...
size_t length = sprintf(FORGET_ABOUT_THIS, "{data:%d}",12312);
型
- p.s.我知道我也可以通过log得到整数的长度,但这种方式似乎更好。*
8条答案
按热度按时间0sgqnhkj1#
由于C语言是简单的语言,因此没有“一次性缓冲区”这样的东西-所有内存管理都在程序员的肩上(有GNU C编译器扩展,但它们不是标准的)。
不能事先知道有多少字符长的整数。
有更简单的解决方案为您的问题.
snprintf
知道!在兼容C99的平台上,调用snprintf,并将NULL作为第一个参数:
字符串
在较旧的Visual Studio版本(具有非C99兼容的CRT)中,使用
_scprintf
而不是snprintf(NULL, ...)
调用。w51jfk4q2#
你可以调用
int len = snprintf(NULL, 0, "{data:%d}", 12312)
来测试你需要多少空间。snprintf
将打印最多size
个字符,其中size
是第二个参数,并返回打印整个内容所需的字符数,不包括终止的'\0'
。因为传入0,它实际上不会写出任何内容(因此将避免任何空指针异常,这将通过尝试解引用NULL
发生),但它仍然会返回适合整个输出所需的长度,您可以使用它来分配缓冲区。此时,您可以分配并打印到您的缓冲区,记住为尾随的
'\0'
添加一个缓冲区:字符串
cedebl8k3#
为了得到长度,你可以这样写:
字符串
请注意,返回类型为
int
。如果出现某种错误,它可能会返回-1
。请确保输入数据不包含长字符串,以免导致总长度超过INT_MAX
!anauzrmj4#
如果您检查性能,您将在没有输出缓冲区的情况下运行snprintf将花费与完全调用大致相同的时间。
因此,我建议您使用较小的缓冲区以防万一,并且只有在返回的大小超过缓冲区大小时才再次调用它。
它使用了C++的
std::string
,但我想你可以根据自己的需要调整它。字符串
与较长的字符串相比,这段代码对1k以下的字符串的运行速度快2倍。
x9ybnkn65#
调用snprintf(nullptr,0,...)确实会返回大小,但它会带来性能损失,因为它会调用IO_str_overflow,而且速度很慢。
如果你真的关心性能,你可以预先分配一个虚拟缓冲区,并将其指针和大小传递给::snprintf。这将比nullptr版本快几倍。
字符串
5jdjgkvh6#
Printf支持%n格式参数,表示“将%n在输出字符串中的位置写入x-参数指向的int值),因此:
字符串
应该可以!
amrnrhlw7#
可以得到一个可重用的函数,它给出任何格式化字符串的长度,使用 vsnprintf:
字符串
示例用法(不使用malloc,而是使用VLA作为缓冲区):
型
jv4diomz8#
这并不是对你的问题的严格回答,但你可能会发现它仍然很有帮助。它不是可移植的,但如果你在glibc上运行它,你可以简单地使用
asprintf()
,它将为你分配内存。