C++ 如何将可变数量的参数传递给printf/sprintf
我有一个类,它包含一个“error”函数,可以格式化一些文本。我想接受数量可变的参数,然后使用printf格式化它们 示例: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
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()是可变函数-它们可以接受可变数量的参数
这基本上包括以下步骤:
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函数是完全安全的。