0

是否有一个简单的 api(无循环)来检查 varargs 是否包含某些值(char *)?

如果没有简单的 API,我应该如何在没有任何 args 计数的情况下进行迭代?

我的方法应该能够根据配置 IP 过滤日志,因此我需要检查其中一个参数是否为 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_);
}

看这节课,只显示给定参数长度和类型的迭代。格式而不是检查包含是昂贵的,记录器应该能够支持高性能需求。

我的目标是实现简单的记录器方法。所以你会这样称呼它:

Log("trafic from ip %s to ip %s", "10.1.1.1","1.1.1.1")

还有很多其他的电话。在过滤器中,我想检查参数值之一是否为“10.1.1.1”(例如),所以不要记录它。

4

3 回答 3

3

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

于 2012-08-25T14:34:48.557 回答
2

没有任何语法糖可以做到这一点,因为没有通用的方法来了解可变参数的类型。在不知道类型的情况下,您无法获得它们的值。所以你必须根据你的函数如何知道它的参数是什么类型来编写代码来做到这一点。

你想这样做:

  1. 将整个日志消息组装到stringstream.

  2. 检查所需字符串的日志消息。

  3. 如果您在其中找到该字符串,请确保它前面或后面没有数字。

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

您需要最后一次检查,因为“foo bar 12.3.4.5 baz”和“foo 2.3.4.51 bar”一样包含“2.3.4.5”。因此,如果您找到该字符串并且它后面或前面有一个数字,您仍然希望记录该消息。

于 2012-08-25T14:34:41.740 回答
-1

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

于 2012-08-25T14:56:54.000 回答