gpt4 book ai didi

c++ - DRY if语句

转载 作者:太空狗 更新时间:2023-10-29 19:44:18 24 4
gpt4 key购买 nike

我有一个 C++ 程序,在许多不同的 .cpp 文件中,我执行如下操作:

if (!thing1.empty() && !thing2.empty())
{
if (thing1.property < thing2.property)
return func1();
else if (thing2.property < thing1.property)
return func2();
else
return func3();
}
else if (!thing1.empty())
{
return func1();
}
else if (!thing2.empty())
{
return func2();
}
else
{
return func4();
}

如果 thing1 大于 thing2,我将尝试以一种方式执行 func,如果情况相反,则向后执行,但如果一个不存在,那么我只对那一半执行 func。然后,如果两者都不存在,我会做一些完全不同的事情。每次使用此模式时,属性、函数和返回类型都不同。对于我想做的事情,有没有比这种丑陋的嵌套 if 语句更好的设计?

编辑: 意识到我的示例代码过于简单化。这是我的一些真实代码,希望能更好地解释问题(尽管它更困惑):

if (!diamondsOnly.empty() && !clubsOnly.empty())
{
if (diamondsOnly.size() < clubsOnly.size())
{
if (passHighCards(player.hand, getHighCards(Card::DIAMONDS), result))
return result;
if (passHighCards(player.hand, getHighCards(Card::CLUBS), result))
return result;
}
else if (clubsOnly.size() < diamondsOnly.size())
{
if (passHighCards(player.hand, getHighCards(Card::CLUBS), result))
return result;
if (passHighCards(player.hand, getHighCards(Card::DIAMONDS), result))
return result;
}
else
{
if (diamondsOnly.back().value > clubsOnly.back().value)
{
if (passHighCards(player.hand, getHighCards(Card::DIAMONDS), result))
return result;
if (passHighCards(player.hand, getHighCards(Card::CLUBS), result))
return result;
}
else
{
if (passHighCards(player.hand, getHighCards(Card::CLUBS), result))
return result;
if (passHighCards(player.hand, getHighCards(Card::DIAMONDS), result))
return result;
}
}
}
else if (!diamondsOnly.empty())
{
if (passHighCards(player.hand, getHighCards(Card::DIAMONDS), result))
return result;
}
else if (!clubsOnly.empty())
{
if (passHighCards(player.hand, getHighCards(Card::CLUBS), result))
return result;
}

最佳答案

先决定再做

查看实际代码时,我首先注意到的是有许多几乎相同的调用,它们仅相差一个常数。我会使用在复杂逻辑中设置的参数在一个地方进行调用。

// Decide what to do.
std::vector<Card::Suit> passOrder;
if (!diamondsOnly.empty() && !clubsOnly.empty()) {
// .. complicated logic that adds suits to passOrder ..
}

// Do it.
for (auto suit : passOrder) { // This is C++11 style -- alter as needed
if (passHighCards(player.hand, getHighCards(suit), result))
return result;
}

(如果 vector 总是只有一两个花色,那么使用 vector 可能有点矫枉过正,但我​​假设真正的代码可能会处理所有花色。)

这样更容易阅读。程序员可以看到,首先您要决定传递卡片的顺序,然后才是真正传递它们。两个单独的步骤将变得更加清晰。只有一个地方调用 passCards 比将它的拷贝分散在整个决策逻辑中更不容易出现愚蠢的拼写错误。它还将使调试变得更容易,因为您可以在非常具体的情况下设置断点,或者您可以只在循环开始时设置断点并检查 passOrder。

简化逻辑

接下来我们要简化决策逻辑。

选项:

  • Sentinels:复杂的部分原因在于,在某些情况下,您需要取消引用其中一个容器中的最后一张卡片,如果容器为空,则无法执行此操作。有时值得考虑向容器添加一个哨兵,这样您就不需要测试空箱——可以保证它永远不会为空。这可能可行也可能不可行。您需要让处理容器的所有其他代码都能理解哨兵。

  • 只是异常(exception):您可以通过选择默认顺序来消除一些子句,例如,方 block 然后是梅花,然后仅测试您需要梅花然后是方 block 的情况。

  • Express with Temporaries:创建名副其实的临时变量,以简化您必须进行的比较,并根据这些临时变量表​​达比较。请注意,将空/非空情况分解为临时情况后,您可以通过选择适当的 SENTINEL_VALUE(例如 0 或 -1)来消除某些情况。

综合起来:

// For readability.
const bool fewerClubs = clubsOnly.size() < diamondsOnly.size();
const bool sameNumber = clubsOnly.size() == diamondsOnly.size();
const int lastDiamondValue = diamondsOnly.empty() ? -1 : diamondsOnly.back().value;
const int lastClubValue = clubsOnly .empty() ? -1 : clubsOnly .back().value;

// Decide what order to select cards for passing.
std::vector<Card::Suit> passOrder;
passOrder.push_back(Cards::DIAMONDS); // default order
passOrder.push_back(Cards::CLUBS);

// Do we need to change the order?
if (fewerClubs || (sameNumber && lastClubValue > lastDiamondValue)) {
// Yep, so start with the clubs instead.
passOrder[0] = Cards::CLUBS;
passOrder[1] = Cards::DIAMONDS;
}

// Do it.
for (auto suit : passOrder) { // This is C++11 style -- alter as needed
if (passHighCards(player.hand, getHighCards(suit), result))
return result;
}

这假设 getHighCards 处理一个可能为空的容器作为输入。

关于c++ - DRY if语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10535962/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com