Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何将可变数量的参数传递给printf/sprintf_C++_C_Printf_Variadic Functions - Fatal编程技术网

C++ 如何将可变数量的参数传递给printf/sprintf

C++ 如何将可变数量的参数传递给printf/sprintf,c++,c,printf,variadic-functions,C++,C,Printf,Variadic Functions,我有一个类,它包含一个“error”函数,可以格式化一些文本。我想接受数量可变的参数,然后使用printf格式化它们 示例: class MyClass { public: void Error(const char* format, ...); }; Error方法应该接收参数,调用printf/sprintf对其进行格式化,然后对其进行处理。我不想自己编写所有格式,因此尝试并找出如何使用现有格式是有意义的。看看vsnprintf,因为这会满足您的需要 您必须首先初始化va_list

我有一个类,它包含一个“error”函数,可以格式化一些文本。我想接受数量可变的参数,然后使用printf格式化它们

示例:

class MyClass
{
public:
    void Error(const char* format, ...);
};

Error方法应该接收参数,调用printf/sprintf对其进行格式化,然后对其进行处理。我不想自己编写所有格式,因此尝试并找出如何使用现有格式是有意义的。

看看vsnprintf,因为这会满足您的需要

您必须首先初始化va_list arg数组,然后调用它

该链接中的示例: /*vsprintf示例*/

#include <stdio.h>
#include <stdarg.h>

void Error (char * format, ...)
{
  char buffer[256];
  va_list args;
  va_start (args, format);
  vsnprintf (buffer, 255, format, args);


  //do something with the error

  va_end (args);
}
#包括
#包括
无效错误(字符*格式,…)
{
字符缓冲区[256];
va_列表参数;
va_开始(参数,格式);
vsnprintf(缓冲区,255,格式,参数);
//对这个错误做点什么
va_端(args);
}

我应该阅读更多关于堆栈溢出中存在问题的内容

这是一个类似的问题。Mike F有以下解释:

没有办法叫printf 不知道有多少争论 除非你愿意,否则你就要过关了 进入顽皮和不可携带的状态 把戏

通常使用的解决方案是 始终提供另一种形式的 vararg函数,因此printf vprintf,它将va_列表置于适当位置 关于。。。。这个版本只是 围绕va_列表版本的包装

这正是我想要的。我执行了如下测试实现:

void Error(const char* format, ...)
{
    char dest[1024 * 16];
    va_list argptr;
    va_start(argptr, format);
    vsprintf(dest, format, argptr);
    va_end(argptr);
    printf(dest);
}
#include <sstream>
#include <boost/format.hpp>
#include <iostream>
using namespace std;

class formatted_log_t {
public:
    formatted_log_t(const char* msg ) : fmt(msg) {}
    ~formatted_log_t() { cout << fmt << endl; }

    template <typename T>
    formatted_log_t& operator %(T value) {
        fmt % value;
        return *this;
    }

protected:
    boost::format                fmt;
};

formatted_log_t log(const char* msg) { return formatted_log_t( msg ); }

// use
int main ()
{
    log("hello %s in %d-th time") % "world" % 10000000;
    return 0;
}

看看这个示例,它们将参数的数量传递给方法,但是您可以对其进行操作并适当修改代码(参见示例)。

下面的简单示例。注意,您应该传入一个更大的缓冲区,并测试该缓冲区是否足够大

void Log(LPCWSTR pFormat, ...) 
{
    va_list pArg;
    va_start(pArg, pFormat);
    char buf[1000];
    int len = _vsntprintf(buf, 1000, pFormat, pArg);
    va_end(pArg);
    //do something with buf
}
你在找我。printf()和sprintf()是可变函数-它们可以接受可变数量的参数

这基本上包括以下步骤:

  • 第一个参数必须给出以下参数数量的一些指示。因此,在printf()中,“format”参数给出了这个指示-如果您有5个格式说明符,那么它将再查找5个参数(总共6个参数)。第一个参数可以是整数(例如“myfunction(3,a,b,c)”,其中“3”表示“3个参数”)

  • 然后使用va_start()等函数循环并检索每个连续参数

  • 有很多关于如何做到这一点的教程-祝你好运

    void Error(const char* format, ...)
    {
        va_list argptr;
        va_start(argptr, format);
        vfprintf(stderr, format, argptr);
        va_end(argptr);
    }
    

    如果要在显示字符串之前对其进行操作,并且确实需要先将其存储在缓冲区中,请使用
    vsnprintf
    而不是
    vsprintf
    vsnprintf
    将防止意外的缓冲区溢出错误。

    使用带省略号的函数不是很安全。如果性能不重要对于log函数,请考虑使用运算符重载,如:升压::格式。
    void Error(const char* format, ...)
    {
        char dest[1024 * 16];
        va_list argptr;
        va_start(argptr, format);
        vsprintf(dest, format, argptr);
        va_end(argptr);
        printf(dest);
    }
    
    #include <sstream>
    #include <boost/format.hpp>
    #include <iostream>
    using namespace std;
    
    class formatted_log_t {
    public:
        formatted_log_t(const char* msg ) : fmt(msg) {}
        ~formatted_log_t() { cout << fmt << endl; }
    
        template <typename T>
        formatted_log_t& operator %(T value) {
            fmt % value;
            return *this;
        }
    
    protected:
        boost::format                fmt;
    };
    
    formatted_log_t log(const char* msg) { return formatted_log_t( msg ); }
    
    // use
    int main ()
    {
        log("hello %s in %d-th time") % "world" % 10000000;
        return 0;
    }
    

    最后一个“printf(dest);”格式不正确-它至少也需要一个格式字符串。它不正确,因为字符串是格式字符串,即printf(“字符串”);很好。您可以使用printf(dest),直到dest恰好包含“%s”或“%d”,然后弹出。请使用printf(“%s”,dest)。我只是想指出,核心转储是最好的情况,在服务器代码中这样做,黑客会把你的CPU当成早餐。尝试使用“%.16383s”,这样可以防止数组dest溢出。(允许“\0”终止符)的第二个参数应该是缓冲区长度,包括终止的空字节(“\0”)所以你可以在函数调用中使用256而不是255,并且传递魔法数是不好的…使用<代码> sisiOf(缓冲器)而不是256。这是如何使一个简单的事情变得困难。“使用椭圆函数不是很安全。”如果你唯一的安全选择涉及C++和Boost,你应该解释你的意思是“不太安全”。,并指出如果使用正确的格式说明符,printf函数是完全安全的。