给定C中的printf语句,如何构造char*缓冲区并知道其长度?
我有一个需要打印到文件中的MPI进程。MPI系统使用诸如MPI_File_iwrite之类的函数命令,这些命令接受一个缓冲区(例如,一个字符指针)和一个整数长度。然后,将缓冲区打印到文件中 因此,为了将需要打印的内容打印到文件中,我需要以某种方式将printf函数替换为将格式转换映射到char*缓冲区的函数。这是有问题的,因为字符串的长度可能不同…例如:给定C中的printf语句,如何构造char*缓冲区并知道其长度?,c,printf,mpi,output-formatting,C,Printf,Mpi,Output Formatting,我有一个需要打印到文件中的MPI进程。MPI系统使用诸如MPI_File_iwrite之类的函数命令,这些命令接受一个缓冲区(例如,一个字符指针)和一个整数长度。然后,将缓冲区打印到文件中 因此,为了将需要打印的内容打印到文件中,我需要以某种方式将printf函数替换为将格式转换映射到char*缓冲区的函数。这是有问题的,因为字符串的长度可能不同…例如: printf("something %d, %d, %d, %f, etc.",x,y,z,p,d,...); 如何恢复printf格式化生
printf("something %d, %d, %d, %f, etc.",x,y,z,p,d,...);
如何恢复printf格式化生成的字符串,计算长度,并将其作为char*传递给mpi函数?看起来您希望使用足够大的缓冲区
如果缓冲区足够大,
snprintf
的返回值等于打印的字符数。您可以将输出字符串的长度计算为缓冲区大小的最小值和snprintf
的返回值。基于您的问题,我认为答案是使用sprintf()
或snprintf()
而不是printf()
-sprintf()
输出到缓冲区并返回写入的字符数,而不检查传递的缓冲区是否足够大snprintf()
接受一个附加参数,指定要写入的最大字节数(这是更安全的方法)
请注意,sprintf()
和变体还需要为终止符\0
添加一个字节,因此这应该反映在您定义的缓冲区大小中。返回值(写入的字节数)不包括终止符。您可以使用将0个字节“打印”到NULL
指针。在这种情况下,不会写入任何字符串,但是snprintf()
相对于其返回值仍将正常运行。然后可以分配足够大的缓冲区
例如:
size_t len;
len = snprintf(NULL, 0, "something %d, %d, %d, %f, etc.",x,y,z,p,d,...);
if (len > 0) {
char *buf = malloc(len + 1);
snprintf(buf, len + 1, "something %d, %d, %d, %f, etc.",x,y,z,p,d,...);
}
这仅在C99及更高版本中有效
请注意,如果存在转换错误,
snprintf()
可能返回负值。这只是少数几个可能发生的情况,但它们仍然存在。根据说明符的不同,其输出也可能为零。您不需要使用strlen()
snprintf()
告诉您应该提供多少个字符。如果您提供的字符数太少,则输出将被截断。snprintf
的整体思想是,它可以使用空缓冲区进行“干运行”,以预先计算所需的缓冲区长度。因此,如果您有snprintf
供您使用,请使用它的功能:以两次通过的方式进行操作。当然,如果可以很容易地预测最大缓冲区长度,那么可以一次性完成。不需要strlen,因为所有的…printf
函数都返回它们输出的序列长度。@AnT如果你有堆栈空间,根据我的经验,使用一个固定大小的本地字符
数组执行第一次snprintf()
调用会更有效,因为该数组足够大,可能在大多数时间都可以工作,只有当固定缓冲区太小时,才动态分配足够大的缓冲区,并再次调用snprintf()
snprintf()
可能有点贵,而且malloc()
可能需要锁定,这可能会影响性能,特别是对于多线程进程。@AndreiTumbar接受;由于空终止符,您必须在snprintf的返回值中添加1才能获得最小缓冲区大小。总的来说,最好忘记sprintf()
及其相关项的存在;您实际上应该只使用snprintf()
,因为它们可以防止缓冲区溢出。也就是说,如果您确信缓冲区足够大,输出数据足够小,sprintf()
仍然可以使用,但最好先强调snprintf()
,然后在一次性注释中提到sprintf()
。此代码的用户需要记住调用free()buf
之后的onbuf
不再需要防止内存泄漏。注意:snprintf()
返回一个int
。负返回值表示错误。输出错误。是否有任何可检测的输出错误snprintf()
可以处理?@giusti:是的:在格式字符串或当前locale1的字符串参数的多字节序列中存在编码错误)printf
是一个函数,而不是一个语句。2) printf
不生成字符串(分别是char[]
.3)char*
是指向char
的指针,而不是数组。如果printf()
执行类似printf(“%c”,0)的操作代码>,然后尝试使用s(n)printf(一些缓冲区,…);len=strlen(一些缓冲区)代码>将无法确定正确的打印字符数。最好使用返回值snprintf()
。
size_t len;
len = snprintf(NULL, 0, "something %d, %d, %d, %f, etc.",x,y,z,p,d,...);
if (len > 0) {
char *buf = malloc(len + 1);
snprintf(buf, len + 1, "something %d, %d, %d, %f, etc.",x,y,z,p,d,...);
}