C-用va_args打印一个参数



i具有实现printf自定义变体的函数。有人知道如何使用va_list打印出一个更多参数?我的格式就像"%d some text %s"。我需要a,以第一个参数印刷。

void func (int a, char *fmt, ...) {
    va_list ap;
    va_start (ap, fmt);
    // vprintf(stdout, fmt, a, ap) //Can't do like this :( 
    vfprintf(fmt, a, ap);          //Or like this :( 
    va_end(ap);
}

如果始终以相同的方式打印a,则不应是传递格式的一部分。您应该单独打印。

在您给出的示例中,将格式字符串更改为 "some text %s"。那么您的功能可以做到这一点:

void func (int a, char *fmt, ...) {
    va_list ap;
    // first print the function specific fields
    printf("%d ", a);
    // then the user's format
    va_start (ap, fmt);
    vprintf(fmt, ap);
    va_end(ap);
}

如注释中所述:

重新设计接口

您将最好重新设计接口,以便格式字符串仅适用于...va_list)参数;固定的参数分别处理。

想要额外参数的标准原因是记录诸如__FILE____LINE__之类的内容(如果您没有C99 __VA_ARGS__支持,则可能不是__func__,请参见下文)。您可能会尽力删除这些固定参数的呼叫者控制格式的选项,而fmt仅处理...参数。

如果您不能重新设计接口

%d是格式的一部分,int值不是va_list的一部分。

如果您不能或拒绝更改调用该功能的规则,则需要解析格式,例如将其分为(但不包括)第二个%,并使用该格式与独立的论点;然后,格式的其余部分将传递给vprintf()。如果您正在使用POSIX系统和多线程程序中,则可能需要在Stdout上使用flockfile()funlockfile(),以确保尽管有多线程,但仍将它们视为单个输出单位。

// Using C99 features
void func(int a, char *fmt, ...)
{
    char *p1 = strchr(fmt, '%');
    if (p1 == 0)
    {
        // No conversion specifications. Not puts(); it adds a newline
        fputs(fmt, stdout);
        return;
    }
    char *p2 = strchr(p1 + 1, '%');
    if (p2 == 0)
    {
        // The user invoked func(1, "iteration %d:n");?
        printf(fmt, a);
        return;
    }
    int buflen = p2 - fmt + 1;
    char buffer[buflen];
    memmove(buffer, fmt, buflen);
    buffer[buflen-1] = '';
    // flockfile(stdout);    // Multi-threading
    printf(buffer, a);
    va_list ap;
    va_start(ap, fmt);
    vprintf(p2, ap);
    va_end(ap);
    // funlockfile(stdout);  // Multi-threading
}

代码作弊;它使用C99 VLA(可变长度阵列)以及交错的声明和语句。因此,在C90中,您可能最终会使用malloc(),或者可能使用固定尺寸的缓冲区(运行溢出风险)或混合动力车(如果格式字符串的前缀足够适合或适合,请使用固定尺寸的缓冲区分配(免费)(如果不是))。

您需要决定适当的错误处理策略。请注意,这不是防弹代码。调用func(a, "%% yield is %d; data is [%s]n", data);在工作中抛出另一个扳手。另外,如果您在Posix上,并且有人通过"它是%2 $ s,并且%1 $ D发生了事情",那么您会遇到深刻的麻烦。

是的,我正在使用Posix系统。但是它很旧,我什至无法使用__VA_ARGS__宏的方法,因为它显示在C99 标准中。

很好奇您在这样的旧系统上。但是,这仅意味着您可能不会用其中的n$表示代码编写代码,因此要担心的是一件事。多线程问题也不太可能成为问题。而且您无法使用我的示例代码中显示的其他C99功能。

您可以查看FFI(外函数接口)库;我根本不确定它会有所帮助。

基于对解析格式的先前答案,我找到了一个简单的解决方案(如果%d始终是首先):

 void func (int a, char *fmt, ...) {
    char *new_format = malloc(10*sizeof(char));
    snprintf(new_format, 10, "%d", a);
    strcat(new_format, (fmt+2));
    va_list ap;
    va_start (ap, fmt);
    vprintf(stdout, new_format, ap);
    va_end(ap);
}

特别感谢Jonathan Leffler

相关内容

  • 没有找到相关文章

最新更新