我有一个类包含一个“错误”函数,它将格式化一些文本。我想接受可变数量的参数,然后使用 printf 格式化它们。
例子:
class MyClass
{
public:
void Error(const char* format, ...);
};
Error 方法应该接受参数,调用 printf/sprintf 对其进行格式化,然后对其进行处理。我不想自己编写所有格式,因此尝试弄清楚如何使用现有格式是有意义的。
我有一个类包含一个“错误”函数,它将格式化一些文本。我想接受可变数量的参数,然后使用 printf 格式化它们。
例子:
class MyClass
{
public:
void Error(const char* format, ...);
};
Error 方法应该接受参数,调用 printf/sprintf 对其进行格式化,然后对其进行处理。我不想自己编写所有格式,因此尝试弄清楚如何使用现有格式是有意义的。
void Error(const char* format, ...)
{
va_list argptr;
va_start(argptr, format);
vfprintf(stderr, format, argptr);
va_end(argptr);
}
如果您想在显示字符串之前对其进行操作,并且确实需要先将其存储在缓冲区中,请使用vsnprintf
而不是vsprintf
. vsnprintf
将防止意外的缓冲区溢出错误。
看看 vsnprintf 因为这会做你想要的http://www.cplusplus.com/reference/clibrary/cstdio/vsprintf/
您必须先初始化 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);
}
我应该阅读更多关于堆栈溢出中现有问题的信息。
C++ Passing Variable Number of Arguments是一个类似的问题。Mike F 有以下解释:
在不知道传递给它的参数数量的情况下,没有办法调用(例如)printf,除非您想使用顽皮和不可移植的技巧。
通常使用的解决方案是始终提供可变参数函数的替代形式,因此 printf 具有 vprintf ,它使用 va_list 代替 ...。 ... 版本只是 va_list 版本的包装器。
这正是我一直在寻找的。我执行了这样的测试实现:
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);
}
您正在寻找可变参数函数。printf() 和 sprintf() 是可变参数函数——它们可以接受可变数量的参数。
这基本上需要以下步骤:
第一个参数必须说明后面的参数数量。所以在 printf() 中,“format”参数给出了这个指示——如果你有 5 个格式说明符,那么它会再寻找 5 个参数(总共 6 个参数)。第一个参数可以是一个整数(例如“myfunction” (3, a, b, c)”,其中“3”表示“3 个参数”
然后使用 va_start() 等函数循环并检索每个连续的参数。
有很多关于如何做到这一点的教程——祝你好运!
下面的简单例子。请注意,您应该传入更大的缓冲区,并测试缓冲区是否足够大
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
}
使用带有省略号的函数不是很安全。如果性能对日志功能不重要,请考虑使用运算符重载,如 boost::format。你可以这样写:
#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;
}
以下示例演示了省略号可能出现的错误:
int x = SOME_VALUE;
double y = SOME_MORE_VALUE;
printf( "some var = %f, other one %f", y, x ); // no errors at compile time, but error at runtime. compiler do not know types you wanted
log( "some var = %f, other one %f" ) % y % x; // no errors. %f only for compatibility. you could write %1% instead.
查看示例http://www.cplusplus.com/reference/clibrary/cstdarg/va_arg/,它们将参数的数量传递给方法,但您可以省略它并适当地修改代码(参见示例)。