Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
给定C中的printf语句,如何构造char*缓冲区并知道其长度?_C_Printf_Mpi_Output Formatting - Fatal编程技术网

给定C中的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格式化生

我有一个需要打印到文件中的MPI进程。MPI系统使用诸如MPI_File_iwrite之类的函数命令,这些命令接受一个缓冲区(例如,一个字符指针)和一个整数长度。然后,将缓冲区打印到文件中

因此,为了将需要打印的内容打印到文件中,我需要以某种方式将printf函数替换为将格式转换映射到char*缓冲区的函数。这是有问题的,因为字符串的长度可能不同…例如:

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
之后的
on
buf
不再需要防止内存泄漏。注意:
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,...);
}