是否有一个简单的api(没有循环)来检查varargs是否包含某些值(char *)?
如果没有简单的API,我应该如何迭代而不计算任何args?
我的方法应该能够过滤配置IP上的日志,所以我需要检查其中一个args是否为10.3.2.2(某些配置IP)。
void Logger::Log(const char *format, ...) {
lock_guard<mutex> guard(mtx_);
if (!file_) {
file_ = fopen("application.log", "w");
}
time_t current = time(0);
tm *ptm = localtime(¤t);
stringstream ss;
ss << "\n[" << ptm->tm_min << ":" << ptm->tm_sec << "]";
fprintf(file_, ss.str().data());
va_list argptr;
va_start(argptr, format);
vfprintf(file_, format, argptr);
va_end(argptr);
fflush(file_);
}
查看此lesson,仅显示给定args长度和类型的迭代。 格式和检查包含是昂贵的,记录器应该能够支持高性能的需求。
我的目标是实现简单的记录器方法。所以你会这样称呼它:
Log("trafic from ip %s to ip %s", "10.1.1.1","1.1.1.1")
以及许多其他电话。在过滤器中我想检查其中一个参数值是否为“10.1.1.1”(例如),所以不要记录它。
答案 0 :(得分:3)
不,没有。无论如何你不应该在c ++中使用varargs,而是使用可变参数模板。
答案 1 :(得分:2)
没有任何语法糖可以做到这一点,因为没有通用的方法来了解varargs的类型。如果不知道类型,就无法获得它们的价值。因此,您必须根据函数如何知道其参数的类型来编写代码来执行此操作。
你想这样做:
在stringstream
。
检查日志消息中是否有所需的字符串。
如果您在其中找到字符串,请确保不前面或后跟数字。
如果您找到该字符串并且其前面或后面没有数字,请将其记录下来。
你需要最后一次检查,因为“foo bar 12.3.4.5 baz”包含“2.3.4.5”,“foo 2.3.4.51 bar”也是如此。因此,如果您找到字符串并且后面跟着或前面有数字,您仍然要记录该消息。
答案 2 :(得分:-1)
嗯,不,没有对变量参数列表的索引访问;只是逐项,所以你必须循环它们;这就是vprintf
等的工作方式。当您遍历这些项目时,您需要知道它们的数量,通常是它们的类型,以及按惯例建立的类型。对于vprintf
等,必须至少与格式字符串中的格式说明符一样多,并且每个格式说明符都会告诉您参数的预期类型。您可以采用的另一个约定是使用sentinel值来标记参数列表的结尾;对于同类列表,例如指针列表,空指针可能是可行的标记。