c ++检查varargs是否包含

时间:2012-08-25 14:29:08

标签: c++

是否有一个简单的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(&current);
    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”(例如),所以不要记录它。

3 个答案:

答案 0 :(得分:3)

不,没有。无论如何你不应该在c ++中使用varargs,而是使用可变参数模板。

答案 1 :(得分:2)

没有任何语法糖可以做到这一点,因为没有通用的方法来了解varargs的类型。如果不知道类型,就无法获得它们的价值。因此,您必须根据函数如何知道其参数的类型来编写代码来执行此操作。

你想这样做:

  1. stringstream

  2. 中汇编整个日志消息
  3. 检查日志消息中是否有所需的字符串。

  4. 如果您在其中找到字符串,请确保前面或后跟数字。

  5. 如果您找到该字符串并且其前面或后面没有数字,请将其记录下来。

  6. 你需要最后一次检查,因为“foo bar 12.3.4.5 baz”包含“2.3.4.5”,“foo 2.3.4.51 bar”也是如此。因此,如果您找到字符串并且后面跟着或前面有数字,您仍然要记录该消息。

答案 2 :(得分:-1)

嗯,不,没有对变量参数列表的索引访问;只是逐项,所以你必须循环它们;这就是vprintf等的工作方式。当您遍历这些项目时,您需要知道它们的数量,通常是它们的类型,以及按惯例建立的类型。对于vprintf等,必须至少与格式字符串中的格式说明符一样多,并且每个格式说明符都会告诉您参数的预期类型。您可以采用的另一个约定是使用sentinel值来标记参数列表的结尾;对于同类列表,例如指针列表,空指针可能是可行的标记。