C 具有自动内存分配功能的sprintf()?
我正在搜索一个函数的类似sprintf()的实现,该函数可以自动分配所需的内存。所以我想说C 具有自动内存分配功能的sprintf()?,c,malloc,printf,C,Malloc,Printf,我正在搜索一个函数的类似sprintf()的实现,该函数可以自动分配所需的内存。所以我想说 char* my_str = dynamic_sprintf( "Hello %s, this is a %.*s nice %05d string", a, b, c, d ); my_str检索保存此sprintf()结果的已分配内存的地址 在另一个论坛上,我读到可以这样解决这个问题: #include <stdlib.h> #include <stdio.h> #inclu
char* my_str = dynamic_sprintf( "Hello %s, this is a %.*s nice %05d string", a, b, c, d );
my_str检索保存此sprintf()结果的已分配内存的地址
在另一个论坛上,我读到可以这样解决这个问题:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
char* ret;
char* a = "Hello";
char* b = "World";
int c = 123;
int numbytes;
numbytes = sprintf( (char*)NULL, "%s %d %s!", a, c, b );
printf( "numbytes = %d", numbytes );
ret = (char*)malloc( ( numbytes + 1 ) * sizeof( char ) );
sprintf( ret, "%s %d %s!", a, c, b );
printf( "ret = >%s<\n", ret );
free( ret );
return 0;
}
#包括
#包括
#包括
int main()
{
char*ret;
char*a=“你好”;
char*b=“世界”;
int c=123;
整数单位;
numbytes=sprintf((char*)NULL,“%s%d%s!”,a,c,b);
printf(“numbytes=%d”,numbytes);
ret=(char*)malloc((numbytes+1)*sizeof(char));
sprintf(ret,“%s%d%s!”,a,c,b);
printf(“ret=>%s
如果可能的话,使用——它提供了一种简单的方法来测量将生成的数据的大小,以便分配空间
如果你真的不能这样做,另一种可能是使用fprintf
打印到一个临时文件,以获得大小,分配内存,然后使用sprintf。snprintf
无疑是首选方法
GNU和BSD有和vasprintf,它们的设计目的就是为您这样做。它将为您确定如何分配内存,并且在任何内存分配错误时返回null
asprintf在分配字符串方面做的是正确的——它首先测量大小,然后尝试使用malloc进行分配。如果失败,它将返回null。除非您有自己的内存分配系统阻止使用malloc,否则asprintf是执行此任务的最佳工具
代码如下所示:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
char* ret;
char* a = "Hello";
char* b = "World";
int c = 123;
ret = asprintf( "%s %d %s!", a, c, b );
if (ret == NULL) {
fprintf(stderr, "Error in asprintf\n");
return 1;
}
printf( "ret = >%s<\n", ret );
free( ret );
return 0;
}
#包括
#包括
#包括
int main()
{
char*ret;
char*a=“你好”;
char*b=“世界”;
int c=123;
ret=asprintf(“%s%d%s!”,a,c,b);
if(ret==NULL){
fprintf(stderr,“asprintf中的错误”);
返回1;
}
printf(“ret=>%s如果针对GLib进行链接是一个选项,则库提供的函数完全满足您的需要。从文档中:
类似于标准Csprintf()
功能,但更安全,因为它
计算所需的最大空间
并分配内存来保存
结果。返回的字符串应为
不再使用时使用g_free()
释放
需要
这是原始答案。正如其他人提到的,您需要snprintf
而不是sprintf
。确保snprintf
的第二个参数是zero
。这将防止snprintf
写入第一个参数的NULL
字符串
第二个参数是必需的,因为它告诉snprintf
没有足够的空间写入输出缓冲区。当没有足够的空间时snprintf
返回如果有足够的空间,它将写入的字节数
从这里的链接复制代码
char* get_error_message(char const *msg) {
size_t needed = snprintf(NULL, 0, "%s: %s (%d)", msg, strerror(errno), errno) + 1;
char *buffer = malloc(needed);
sprintf(buffer, "%s: %s (%d)", msg, strerror(errno), errno);
return buffer;
}
如果您可以使用GNU/BSD扩展,那么问题已经得到了回答。您可以使用asprintf()
(和vasprintf()
构建包装函数)并完成
但是根据手册页,POSIX强制使用snprintf()
和vsnprintf()
,后者可用于构建自己的asprintf()
和vasprintf()
的简单版本
您可以使用一些预处理器魔法,并仅在不支持这些功能的系统上使用您的函数版本。POSIX.1(又名IEEE 1003.1-2008)提供了OpenMemstream:
/* casprintf print to allocated or reallocated string
char *aux = NULL;
casprintf(&aux,"first line\n");
casprintf(&aux,"seconde line\n");
printf(aux);
free(aux);
*/
int vcasprintf(char **strp,const char *fmt,va_list ap)
{
int ret;
char *strp1;
char *result;
if (*strp==NULL)
return vasprintf(strp,fmt,ap);
ret=vasprintf(&strp1,fmt,ap); // ret = strlen(strp1) or -1
if (ret == -1 ) return ret;
if (ret==0) {free(strp1);return strlen(*strp);}
size_t len = strlen(*strp);
*strp=realloc(*strp,len + ret +1);
memcpy((*strp)+len,strp1,ret+1);
free(strp1);
return(len+ret);
}
int casprintf(char **strp, const char *fmt, ...)
{
int ret;
va_list ap;
va_start(ap,fmt);
ret =vcasprintf(strp,fmt,ap);
va_end(ap);
return(ret);
}
char *ptr;
size_t size;
FILE *f = open_memstream(&ptr, &size);
fprintf(f, "lots of stuff here\n");
fclose(f);
write(1, ptr, size); /* for example */
free(ptr);
open_memstream(3)至少在Linux和macOS上可用,并且已经使用了一些年。open_memstream(3)的相反版本是fmemopen(3),它使缓冲区的内容可用于读取
如果您只需要一个sprintf(3),那么广泛实现但非标准的asprintf(3)可能就是你想要的。给你这个建议的人可能意味着你应该使用snprintf
,而不是sprintf
。可能是Hello的复制品,谢谢!但这只是glibc,我需要一个平台无关的解决方案。所以也许最好是自己来做?GLib(GTK+的基础),而不是GNU C库(glibc).但它相当于glibc的asprintf.glib是独立于平台的Sprintf()这将是我选择的功能-但不幸的是,它不标准且不可移植-不好!@theshamen-你要求的定义是非标准且不可移植的。获取asprintf
的源代码,如果需要,将其拉入你的项目中,或者独立地重新实现它。我没有听说过asprintf()
返回指针。GNU和BSD附带的指针(由gnulib和libstrl提供)与等价的printf()调用具有相同的返回值,并将指向指针的指针作为第一个参数。因此,char*s;int ret=asprintf(&s,“%s%d%s!”,a,c,b)
在ret==-1
上出现错误。只是想知道,哪些系统/库提供了一个asprintf()
,它返回的指针与此答案类似?您只能将va_list
变量传递给一个函数。要使用vsnprintf()
两次,您应该使用vasprrintf()
。如果您在从vasprintf()
返回之前添加va_end(ap1)
(例如,在调用vsnprintf()
之后)。您忘记在vasprintf的末尾设置strp,代码中有一些错误处理(它处理calloc
的故障)但是如果vsnprintf
失败,它仍然会爆炸:如果小于-1作为第一个vsnprintf
的错误代码返回,那么大小计算就会结束。如果vsnprintf
的第二次调用失败,缓冲区就会泄漏。您不应该在需要的中添加1来解释终止的空字符吗?起初没有在第一行的末尾发现+1(它在可见区域之外)
char *ptr;
size_t size;
FILE *f = open_memstream(&ptr, &size);
fprintf(f, "lots of stuff here\n");
fclose(f);
write(1, ptr, size); /* for example */
free(ptr);