【问题标题】:Is there a way to shorten a long switch() statement?有没有办法缩短长的 switch() 语句?
【发布时间】:2019-09-21 18:56:05
【问题描述】:

我在我的 switch() 语句中处理了很多情况,我想知道是否有任何可能的方法可以缩短这些情况。它们在我的代码中占用了大量空间,当这些语句有 3-4 个大块时,导航变得更加困难。 这是一个例子:

...important lines of code...

void foo(string bar, bool blam) {

     int v1 = stoi(bar);

     switch (v1) {
         case(11):
             if(blam) {
                exArr[1] = "A";
             } else {
                exArr[1] = "B";
             }
             break;

         case(12):
             if(blam) {
                 exArr[3] = "A";
             } else {
                 exArr[3] = "B";
             }
             break;

         ...many more cases...

         default:
             printElement();
             break;
}
...even more important code, which is dependent on the hard code above and hard to navigate...

我认为您看到了问题所在。你们有什么建议吗?提前致谢。

重要编辑:

只有前 12 次迭代会改变 exArr 的字符。之后,它会更改为另一个(现有)数组,例如 ndArr,它需要另外 12 次迭代。这适用于 4 个数组,因此大约有 48 个 case 语句。

【问题讨论】:

  • v1 的值和exArr 中的索引之间是否存在关系,可以写成数学公式?
  • blam 是否总是区分想要的"A""B"
  • 如果代码具有与 sn-p 相同的模式,则只是一个整数数组或std::vector<int>。 index 是 v1 的值,该值是 exArr 中项目的索引。喜欢exArr[map[v1]] = blam ? "A" : "B" 。无需开关。
  • extraArr[1] = blam ? "A" :"B"; 之类的东西至少会更紧凑一些。
  • 如果在每个case 语句中您都在询问blam,那么您可能想要if (blam) { switch()... } else { switch()... } 之类的东西,这意味着您有两个较短的switches 和一个if。

标签: c++ loops switch-statement


【解决方案1】:

正如@Alexander Zhang 所提到的,如果您有可以使用的特定算法,那么解决问题的最简单方法将类似于@Ton van den Heuvel 提出的建议。

如果没有,如果您有匹配的特定值,也可以使用 查找表(引用自 here)。

例如。

#include <map>

.../

map<int,int> mapV1toIndex = {
    {11, 1}, 
    {12, 3},
    .../
};

void foo(string bar, bool blam) {
    int v1 = stoi(bar);
    exArr[mapV1toIndex[v1]] = (blam) ?  "A" : "B";
}

另外,如果你想每次使用不同的字符串数组,你可以像这样将字符串数组传入 foo 以重用 foo 函数:

void foo(string *pStrArray, string bar, bool blam) {
    int v1 = stoi(bar);
    pStrArray[mapV1toIndex[v1]] = (blam) ?  "A" : "B";
}

编辑:最好使用 std::map 而不是结构。按照this 参考,编辑了使用地图的代码。

【讨论】:

  • 我需要对我的结构进行一些测试以确保它可以正常工作,但这将是答案的一般形式,您可能会将其变成 4 个三元语句。
  • 意识到 struct 容器不如简单地使用 std::map 好用。编辑了我的答案以改用地图。
  • 添加了一个关于为多个数组重用 foo 的花絮。
【解决方案2】:

首先,您可以删除 if else 语句上的花括号,因为它们是一个衬里,在这样的 case 块内

...
case(12):
    if(blam)
        exArr[3] = "A";
    else
        exArr[3] = "B";
    break;
...

你可以更进一步,使用看起来像这样的三元运算符

...
case(12):
    exArr[3] = (blam) ?  "A" : "B";
    break;
...

【讨论】:

  • 在他澄清他必须修改不同的数组之前,我添加了这个建议。在那种情况下,正如您所说,您可以使用嵌套的 switch 语句或用例(12): return exArr[1] = blam ? “A”:“B”;
【解决方案3】:

假设v1与后续case的关系照样继续,则不需要切换:

const int v1{stoi(bar)};
if (11 <= v1 && v1 <= ...)
  exArr[1 + (v1 - 11) * 2] = blam ? "A" : "B";
else
  printElement();

【讨论】:

  • 虽然这不是正确的解决方案,因为 OP 显然确实需要一个 switch 语句,但它仍然是一个聪明的主意,我发现反对票是不值得的......
【解决方案4】:

理想情况下,您应该尝试使用多态性来解决这个问题。我在 stackoverflow 上找到了这个,Ways to eliminate switch in code。 该示例未直接在 C++ 中实现,但它会给您一个想法。通过使用多态性,您的代码在未来将更具可读性和可扩展性。

【讨论】:

  • 这仅适用于面向对象的代码。我认为这些缺乏实现的答案应该归入 cmets。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-30
  • 2020-11-17
  • 2014-10-19
  • 2019-12-23
  • 2021-07-01
相关资源
最近更新 更多