switch case 语句的循环复杂度
Cyclomatic Complexity of switch case statement
我对 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");
}
CC 是什么?
我发现a post说是5,有这个图
(边是17,不是16,我觉得打错了)
说我们只需要将case 0和case 1算作一个
但我认为图表应该是:
边数: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
所以应该是 6
正确答案是什么?
我真的很困惑,谢谢。
已编辑:
现在我认为是7。是的,7
因为如果 n 大于 5,将什么都不做并退出 switch 语句。
然后我们得到这张图:
现在 E = 18
18 - 13 + 2 = 7
我说得对吗?
真的,真的,真的很迷茫...
我使用过的代码度量工具将每个案例计为一个单独的分支,即使它是失败的案例。
但这是一个随意的选择。默认情况下,代码度量工具倾向于谨慎行事。最终评估 switch 语句的方式是一个内部实现细节,它会根据输入类型和案例数量(至少在 C# 中)而有所不同。
减少由 switch 语句引起的圈复杂度的首选方法是将 cases/outputs 转换为字典。在您的示例中,它类似于下面的代码示例。请注意,这仅适用于 readability/maintainability。如果您的 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]);
}
好的,我找到答案了。
来自 McCabe.com,第 26 和 27 页
答案是 5,因为 McCabe 的 CC 原始版本将失败案例计为 1。
正确答案是 7。
switch 语句中的每个 case 都计为 1,因此 5 x 1 = 5。
if 算作 1。
else 算作 1。
所以,
1 + (5 x 1) + 1 = 7.
如果您将其视为方法的主体,则 cc 将为 8,因为该方法被视为直通路径。
请将您接受的答案更改为正确答案,因为 5 是错误答案。
我对 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");
}
CC 是什么?
我发现a post说是5,有这个图
(边是17,不是16,我觉得打错了)
说我们只需要将case 0和case 1算作一个
但我认为图表应该是:
边数: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
所以应该是 6
正确答案是什么?
我真的很困惑,谢谢。
已编辑:
现在我认为是7。是的,7
因为如果 n 大于 5,将什么都不做并退出 switch 语句。
然后我们得到这张图:
现在 E = 18
18 - 13 + 2 = 7
我说得对吗?
真的,真的,真的很迷茫...
我使用过的代码度量工具将每个案例计为一个单独的分支,即使它是失败的案例。
但这是一个随意的选择。默认情况下,代码度量工具倾向于谨慎行事。最终评估 switch 语句的方式是一个内部实现细节,它会根据输入类型和案例数量(至少在 C# 中)而有所不同。
减少由 switch 语句引起的圈复杂度的首选方法是将 cases/outputs 转换为字典。在您的示例中,它类似于下面的代码示例。请注意,这仅适用于 readability/maintainability。如果您的 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]);
}
好的,我找到答案了。
来自 McCabe.com,第 26 和 27 页
答案是 5,因为 McCabe 的 CC 原始版本将失败案例计为 1。
正确答案是 7。 switch 语句中的每个 case 都计为 1,因此 5 x 1 = 5。 if 算作 1。 else 算作 1。 所以, 1 + (5 x 1) + 1 = 7.
如果您将其视为方法的主体,则 cc 将为 8,因为该方法被视为直通路径。
请将您接受的答案更改为正确答案,因为 5 是错误答案。