【问题标题】:C, Dealing with variable argument functionsC、处理可变参数函数
【发布时间】:2011-01-26 03:17:04
【问题描述】:

假设我想做这样的事情

void my_printf(char *fmt,...) {
 char buf[big enough];
 sprintf(buf,fmt,...);  
}

将可变数量的参数直接传递给接受可变参数的函数的正确方法是什么?

【问题讨论】:

  • 你怎么知道缓冲区足够大?并且你真的应该返回 sprintf() 执行的转换次数,否则用户无法知道该函数是否有效。
  • 我删除了所有对说明我的观点不重要的内容。显然,在我的发布代码中,我更加彻底:)

标签: c variables arguments


【解决方案1】:

sprintf 有一个名为vsprintfva_list 表单。将您在本地构造的va_list 作为最后一个参数传递给它。

void my_printf(char *fmt,...) {
 va_list ap;
 va_start(ap, fmt);

 char buf[big enough];
 vsprintf(buf,fmt,ap);

 va_end(ap);
}

【讨论】:

  • 操作头是<stdarg.h>
  • 如果可用,您应该使用vsnprintf
【解决方案2】:

我不确定这段代码会有多大用处,因为它是 C++,但它显示了如何使用 Win32 特定函数 vsnprintf() 检查分配的缓冲区是否足够大,如果没有分配更大的缓冲区.它返回一个 std::string,所以你必须使用 malloc/realloc 来处理它。但到底是什么:

string Format( const char * fmt, ... ) {
    const int BUFSIZE = 1024;
    int size = BUFSIZE, rv = -1;
    vector <char> buf( size );
    do {
        va_list valist;
        va_start(valist, fmt );
        // if vsnprintf() returns < 0, the buffer wasn't big enough
        // so increase buffer size and try again
        rv = _vsnprintf( &buf[0], size, fmt, valist );
        va_end( valist );
        size *= 2;
        buf.resize( size );
    }
    while( rv < 0 );
    return string( &buf[0] );
}

【讨论】:

    【解决方案3】:

    您可以使用 vsprintf 样式函数为您的可变长度参数获取 printf 样式打印。但是,没有要求这样做。如果您选择编写函数以继续接受参数,直到遇到空指针,您就可以。

     va_list ap;
    char *param;
    va_start(ap,fmt);
    param = va_arg(ap,char*);
    while(param)
    {
    do something...
    param = va_arg(ap,char*);
    }
    

    或者您可以将参数的数量作为函数的第一个参数

    void my_printf(int param_num,...)
    {
     va_list ap;
    char *param;
    va_start(ap,fmt);
    while(param_num)
    {
    do something...
    param = va_arg(ap,char*);
    param_num--;
    }
    
    }
    

    这完全取决于您,可能性是无限的。我认为对椭圆唯一真正的要求是它在椭圆之前至少有一个参数。

    【讨论】:

    • 要求用户指定参数数量将是设计灾难
    • 我的观点是......不是被归类为某种用法。该功能的用户可以决定什么最适合他们的情况。传入参数的数量与将数字嵌入字符串没有什么不同......即 sprintf("%d %d",a,b) 与 yourprintf(2,a,b) 相同,sprintf 是同样容易出现用户错误。
    猜你喜欢
    • 1970-01-01
    • 2015-07-04
    • 2013-03-14
    • 1970-01-01
    • 2012-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-17
    相关资源
    最近更新 更多