开关案例陈述的循环复杂性

Cod*_*Cat 9 cyclomatic-complexity

我对switch语句的CC感到困惑

如果我有以下代码:

if (n >= 0) {
    switch(n) {
        case 0:
        case 1: 
            printf("zero or one\n");
            break;
        case 2: 
            printf("two\n");
            break;
        case 3:
        case 4: 
            printf("three or four\n");
            break;
        }
    }
else {
    printf ("negative\n");
}
Run Code Online (Sandbox Code Playgroud)

什么是CC?

我发现一个帖子说它是5,用这个图表 CC图

(边缘是17,而不是16,我认为这是一个错字)

它说我们只需要将案例0和案例1统一为一

但我认为图表应该是: CC图

边缘:17,
节点:
13,17 - 13 + 2P = 6

我将每个案例都算作1

我的OOSE教授说这是6,但方式不同

他说:

init     => 1  
if       => 1  
switch   => 1  
case 0 1 => 1  
case 2   => 1  
case 3 4 => 1
Run Code Online (Sandbox Code Playgroud)

所以它应该是6

什么是正确的答案?
我真的很困惑,谢谢.


编辑:
现在我认为是 7.是,7
因为如果n大于5,则不执行任何操作并退出switch语句.

然后我们得到这个图:
在此输入图像描述

现在E = 18
18 - 13 + 2 = 7

我对么..?
真的,真的,真的很困惑......

Cod*_*Cat 7

好的,我找到了答案。

来自 McCabe.com

http://www.mccabe.com/pdf/mccabe-nist235r.pdf

第 26 和 27 页

答案是 5,因为 McCabe 的原始版本 CC 将失败案例计为 1。


Set*_*eth 6

我使用过的代码度量工具将每个案例视为一个单独的分支,即使它是失败案例。

但这是一个随意的选择。默认情况下,代码度量工具倾向于谨慎行事。最终评估 switch 语句的方式是一个内部实现细节,它会根据输入类型和案例数量(至少在 C# 中)而有所不同。

减少由 switch 语句引起的圈复杂度的首选答案是将案例/输出转换为字典。在您的示例中,它类似于下面的代码示例。请注意,这只是为了可读性/可维护性。如果您的 switch 语句足够长,.Net 编译器会自动为您将其转换为字典,因此不会提高性能。

var outputs = new Dictionary<int, string>()
            {
                { 0, "zero or one\n" },
                { 1, "zero or one\n" },
                { 2, "two\n" },
                { 3, "three or four\n" },
                { 4, "three or four\n" }
            };

if (n >= 0)
{
    printf(outputs[n]);
}
Run Code Online (Sandbox Code Playgroud)