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

时间:2008-12-29 21:13:53

标签: c++ parsing macros

我有一个看起来像这样的宏:

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

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

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&lt;&lt; ...; else“以确定是否有任何其他情况发生这种情况以确保在修复宏时,它确实是正确的功能。

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

6 个答案:

答案 0 :(得分:2)

您可以尝试 - 暂时 - 将宏修改为类似的内容,并查看无法编译的内容......

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

'else'条款现在应该出错。

答案 1 :(得分:2)

不要试图找到代码中发生逻辑错误的所有位置 - 从源头解决问题!更改宏,以便不会出现错误:

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

请注意,我在这里所做的是反转测试,为then子句添加一个空语句,并将输出对象放在else子句中。这仍允许您在宏之后使用<< foo << bar,如果您有一个属于不同else语句的尾随if子句,它将正确匹配,因为它会像这样扩展:

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

变为

if(foo)
    if(VERBOSITY_SETTING < VERBOSITY_ERROR)
        ;
    else
        ods() << bar;
else
    baz();

答案 2 :(得分:1)

我认为宏的所有良好用法都以'{'或';'。

开头

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

[^{;]\s*coutError

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

您可能需要获取更多内容,以便找到有问题的行: - )

如果我们能够解决一些失败的问题,那么改变宏是一个很好的想法。可能是一个块后跟条件运算符:

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

(但确实需要实现一个nullstream()运算符。)

(或者完全暂时删除条件 - 正如你的建议是对另一个答案@Roddy(目前是选定的答案)的评论)。

P.S。我知道你没有问,但是用一个do {} while(false)循环来包装宏以保证其安全的简单方法。

答案 3 :(得分:1)

我在上面的评论中看到你正在考虑在宏中使用模板,我还不能发表评论(我只差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&lt;&lt; inString?

我不会尝试使用宏来模仿&lt;&lt;语法,如果没有明确的收益。至少使用模拟函数语法的宏我们更常用,我们知道我们必须编写块以防止出现奇怪的问题。

你真的需要&lt;&lt;语法?

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

哦,最后一件事 - 不要使用宏。

答案 4 :(得分:0)

我认为真正的问题是使用宏 - 而不是预处理的代码。但我不认为这是你正在寻找的答案。

我会找到一种方法来完成它而不使用宏 - 如果你使用条件编译,你可以在调用ods()时这样做 - 取决于一些#define它可以使用你想要的任何功能。 / p>

只是我的$ .02

答案 5 :(得分:0)

正则表达式搜索?