我有一个类,其中包含一个“错误”函数,该函数将格式化某些文本。我想接受可变数量的参数,然后使用printf格式化它们。
例:
class MyClass
{
public:
void Error(const char* format, ...);
};
Error方法应该接受参数,调用printf / sprintf对其进行格式化,然后对其进行处理。我不想自己写所有格式,因此尝试弄清楚如何使用现有格式很有意义。
Answers:
看看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);
}
sizeof(buffer)
,而不是256
我应该阅读有关堆栈溢出中现有问题的更多信息。
C ++传递可变数量的参数是一个类似的问题。Mike F有以下解释:
在不知道要传递给它多少个参数的情况下,无法调用(例如)printf,除非您想陷入顽皮和不可移植的窍门。
通常使用的解决方案是始终提供另一种形式的vararg函数,因此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);
}
在椭圆上使用函数不是很安全。如果性能对日志功能不是很关键,请考虑像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/,它们将参数数量传递给方法,但是您可以忽略该参数并适当地修改代码(请参见示例)。