sprintf()与自动内存分配?

我正在寻找一个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> #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; } 

但是,当带有NULL指针的sprintf()被调用时,立即导致段错误。

那么任何想法,解决scheme或提示? 放置在公共领域的sprintf()类似的parsing器的一个小实现已经足够了,然后我可以自己完成。

非常感谢!

这是Stack Overflow的原始答案。 正如其他人所说的,你需要snprintf而不是sprintf 。 确保snprintf的第二个参数是zero 。 这将阻止snprintf写入第一个参数的NULLstring。

第二个参数是必需的,因为它告诉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); snprintf(buffer, needed, "%s: %s (%d)", msg, strerror(errno), errno); return buffer; } 

GNU和BSD有asprintf和vasprintf,这些都是为你做的。 它会弄清楚如何为你分配内存,并在任何内存分配错误时返回null。

asprintf在分配string方面做了正确的事情 – 它首先测量大小,然后尝试使用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; } 
  1. 如果可能的话,使用snprintf – 它提供了一种简单的方法来衡量将生成的数据的大小,以便您可以分配空间。
  2. 如果你真的无法做到这一点,另一种可能是用fprintf打印临时文件来获得大小,分配内存,然后使用sprintf。 snprintf 绝对是首选的方法。

如果你能忍受GNU / BSD的延伸,这个问题已经得到解答。 您可以使用asprintf() (和vasprintf()来构build包装函数)并完成。

但是,根据手册页,POSIX要求snprintf()vsnprintf() ,后者可以用来构build自己的简单版本的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; } 

你可以做一些预处理器的魔术,只在不支持它们的系统上使用你的函数版本。

GLib库提供了一个g_strdup_printf函数,它完全符合你的要求,如果与GLib链接是一个选项。 从文档:

与标准的C sprintf()函数类似,但更安全,因为它计算所需的最大空间并分配内存来保存结果。 不再需要时,返回的string应该用g_free()来释放。