我正在寻找一个sprintf() - 类似于自动分配所需内存的函数的实现.所以我想说
char* my_str = dynamic_sprintf( "Hello %s, this is a %.*s nice %05d string", a, b, c, d );
Run Code Online (Sandbox Code Playgroud)
和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;
}
Run Code Online (Sandbox Code Playgroud)
但是当调用带有NULL指针的sprintf()时,这会立即导致段错误.
那么任何想法,解决方案或提示?sprintf()的一个小实现 - 就像放置在公共域中的解析器一样,已经可以实现,然后我可以自己完成它.
非常感谢!
小智 36
这是Stack Overflow的原始答案.正如其他人所说,你需要的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;
}
Run Code Online (Sandbox Code Playgroud)
Mik*_*iak 25
GNU和BSD有asprintf和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;
}
Run Code Online (Sandbox Code Playgroud)
Pav*_*rda 13
如果您可以使用GNU/BSD扩展,则问题已经得到解答.您可以使用asprintf()(以及vasprintf()构建包装函数)并完成.
但snprintf()和vsnprintf()被POSIX强制,根据手册页,而后者可以用来建立的自己的简单版本asprintf()和vasprintf().
int
vasprintf(char **strp, const char *fmt, va_list ap)
{
va_list ap1;
size_t size;
char *buffer;
va_copy(ap1, ap);
size = vsnprintf(NULL, 0, fmt, ap1) + 1;
va_end(ap1);
buffer = calloc(1, size);
if (!buffer)
return -1;
*strp = buffer;
return vsnprintf(buffer, size, fmt, ap);
}
int
asprintf(char **strp, const char *fmt, ...)
{
int error;
va_list ap;
va_start(ap, fmt);
error = vasprintf(strp, fmt, ap);
va_end(ap);
return error;
}
Run Code Online (Sandbox Code Playgroud)
您可以执行一些预处理器魔术,并仅在不支持它们的系统上使用您的函数版本.
该GLib库库提供了一个g_strdup_printf功能,你想要做什么,如果链接到的GLib的是一种选择.从文档:
与标准C
sprintf()函数类似但更安全,因为它计算所需的最大空间并分配内存来保存结果.g_free()不再需要时,应释放返回的字符串.