代码之家  ›  专栏  ›  技术社区  ›  FryGuy

在C++文件中查找语句模式

  •  2
  • FryGuy  · 技术社区  · 16 年前

    我有一个像这样的宏:

    #define coutError    if (VERBOSITY_SETTING >= VERBOSITY_ERROR)    ods()
    

    其中ods()是一个行为类似于cout的类,而verbosity_设置是一个全局变量。对于不同的详细设置,有一些这样的设置,它允许代码看起来像这样:

    if (someErrorCondition)
    {
        // ... do things relating to the error condition ...
    
        coutError << "Error condition occurred";
    }
    

    这个框架中有设置冗长性的功能,等等。但是,当不在类似这样的地方使用大括号时,明显的模式会中断:

    void LightSwitch::TurnOn()
    {
        if (!PowerToSwitch)
            coutError << "No power!";
        else
            SwitchOn = true;
    }
    

    由于宏,将变成:

    void LightSwitch::TurnOn()
    {
        if (!PowerToSwitch)
            if (VERBOSITY_SETTING >= VERBOSITY_ERROR)
                ods() << "No power!";
            else
                SwitchOn = true;
    }
    

    这不是if语句的预期功能。

    现在,我了解了一种正确修复宏的方法,这样它就不会导致这个问题,但我想对代码进行审计,并找到任何具有“if(…)couterror<…;else”模式的地方,以查明是否有其他情况发生,以确保在修复宏时,它确实具有正确的功能。是的。

    我可以使用任何语言/工具来找到这个,我只是想知道最好的方法。

    6 回复  |  直到 16 年前
        1
  •  2
  •   Roddy    16 年前

    您可以尝试-临时-将宏修改为类似这样的内容,然后查看什么不能编译…

    #define coutError {} if (VERBOSITY_SETTING >= VERBOSITY_ERROR) ods()
    

    “else”子句现在应该给出错误。

        2
  •  2
  •   Adam Rosenfield    16 年前

    不要费心去寻找代码中发生逻辑错误的所有位置——在源代码处修复问题!更改宏,使其不可能出错:

    #define coutError if(VERBOSITY_SETTING < VERBOSITY_ERROR); else ods()
    

    请注意,我在这里所做的是颠倒测试,为 then 子句,并将输出对象放入 else 条款。这仍然允许你使用 << foo << bar 在宏之后,如果您有一个 其他的 属于不同的子句 if 语句,它将正确匹配,因为它的扩展方式如下:

    if(foo)
        coutError << bar;
    else
        baz();
    

    变成

    if(foo)
        if(VERBOSITY_SETTING < VERBOSITY_ERROR)
            ;
        else
            ods() << bar;
    else
        baz();
    
        3
  •  1
  •   Douglas Leeder    16 年前

    我认为宏的所有好用法都以“”或“;”开头。

    所以试试这个正则表达式:

    [^{;]\s*coutError
    

    您需要启用多行匹配,并针对整个文件进行搜索。

    您可能需要抓取更多的东西,以便找到相关行:—)

    或者,改变宏是一个很好的主意,如果我们能计算出一些会正确失败的东西。可能是一个块,后面跟着条件运算符:

    #define coutError {} (VERBOSITY_SETTING >= VERBOSITY_ERROR)?(ods()):(nullstream()) 
    

    (但不需要实现nullstream()运算符。)

    (或者暂时完全消除条件-正如您建议的,是对另一个答案@roddy(当前所选答案)的注释)。

    另外,我知道你没有问,但一个简单的方法是用一个 do {} while(false) 循环。

        4
  •  1
  •   Daniel Daranas    16 年前

    我在你上面的评论中看到你正在考虑在宏中使用一个模板,我还不能评论(我比它少了9点),所以…

    什么阻止你做

    #define CoutError(s) { if (VERBOSITY_SETTING >= VERBOSITY_ERROR){ ods(s); } }
    

    然后

    void LightSwitch::TurnOn()
    {
        if (!PowerToSwitch)
            CoutError("No power!");
        else
            SwitchOn = true;
    }
    

    并重新定义ods以允许一个字符串,或者,如果不能,则只需定义一个odshelper函数,该函数接受一个字符串,其主体只是ods<<instring?

    如果没有明确的收获,我不会使用试图模仿<<语法的宏。至少对于模拟函数语法的宏,我们更常用,而且我们知道必须编写块来防止奇怪的问题。

    您真的需要<<语法吗?

    你真的需要为这个简单的行为介绍一个模板吗?

    还有最后一件事-不要使用宏。

        5
  •  0
  •   Tim    16 年前

    我认为真正的问题是宏的使用,而不是预处理的代码。但我不认为这是你想要的答案。

    我会找到一种不使用宏的方法——如果使用条件编译,可以在对ods()的调用中这样做——这取决于某些定义,它可以使用您想要的任何功能。

    我的02美元

        6
  •  0
  •   Jim Buck    16 年前

    正则表达式搜索?