每个字符串参数的长度

rph*_*hii 1 c arguments args

最近我开始对stdarg.h函数有了一些了解,因为我想要一些类似于printf但不是写入控制台的东西,我想将它作为字符串返回。

到目前为止,这是我想出的:

char *write(const char *format, ...)
{
    // init
    va_list arg;
    char *string;

    va_start (arg, format);
    vsprintf (string, format, arg);

    // done
    va_end (arg);
    return string;
}
Run Code Online (Sandbox Code Playgroud)

现在的问题是,它string没有保留内存,这就是我需要帮助解决此功能的地方,因为我还没有找到任何解决方案。

提前致谢

Kam*_*Cuk 5

使用snprintf(NULL, 0检查多久缓冲你的需要。然后分配内存。然后打印到字符串。

char *my_write(const char *format, ...) {
    va_list va;
    va_start(va, format);

    // remember to have a separate va_list for each v*print function
    va_list va2;
    va_copy(va2, va);
    const int len = vsnprintf(NULL, 0, format, va2);
    va_end(va2);

    char *string = malloc((len + 1) * sizeof(*string));
    if (string != NULL) {
       vsprintf(string, format, va);
    }
    va_end(va);

    return string;
}
Run Code Online (Sandbox Code Playgroud)

正如@IanAbbott 在评论中所建议的,您可以调用va_start两次,这似乎很好地简化了代码:

char *my_write(const char *format, ...) {
    va_list va;

    va_start(va, format);
    const int len = vsnprintf(NULL, 0, format, va);
    va_end(va);

    char *string = malloc((len + 1) * sizeof(*string));
    if (string == NULL) {
       return NULL;
    }

    va_start(va, format);
    vsprintf(string, format, va);
    va_end(va);

    return string;
}
Run Code Online (Sandbox Code Playgroud)

在带有 glibc 的平台上,您还可以使用vasprintf. 请注意,该名称write已被posix write() 函数使用,我建议使用不同的名称。有了vasprintfGNU 扩展,它就变成了:

#define _GNU_SOURCE
#include <stdio.h>
char *write2(const char *format, ...) {
    va_list va;
    va_start(va, format);
    char *string;
    const int err = vasprintf(&string, format, va);
    va_end(va);
    if (err == -1) {
          return NULL;
    }
    return string;
}
Run Code Online (Sandbox Code Playgroud)

  • 在 `va_start(va, format);` 和 `va_end(va);` 之后,可以通过再次调用 `va_start(va, format);` 来重复使用 `va` 变量,所以不应该这段代码中是否需要“va2”和“va_copy(va2, va);”。 (3认同)