Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
干if语句 我有一个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(); } if(!thing1.empty()&&&!thing2.empty()) { if(thing1.property_C++_If Statement_Dry - Fatal编程技术网

干if语句 我有一个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(); } if(!thing1.empty()&&&!thing2.empty()) { if(thing1.property

干if语句 我有一个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(); } if(!thing1.empty()&&&!thing2.empty()) { if(thing1.property,c++,if-statement,dry,C++,If Statement,Dry,如果1比2大,我试着用一种方法来做func,如果相反,我试着用反向的方法来做,但是如果一个不存在,我只做那一半的func。如果两者都不存在,我会做一些完全不同的事情。每次使用此模式时,属性、函数和返回类型都不同。对于我想做的事情,有没有比这种糟糕的嵌套if语句更好的设计 编辑:意识到我的示例代码过于简单。下面是我的一段真实代码,希望它能更好地解释这个问题(尽管它要复杂得多): if(!diamondsOnly.empty()&&!clubsOnly.empty()) { if(diamondsO

如果1比2大,我试着用一种方法来做func,如果相反,我试着用反向的方法来做,但是如果一个不存在,我只做那一半的func。如果两者都不存在,我会做一些完全不同的事情。每次使用此模式时,属性、函数和返回类型都不同。对于我想做的事情,有没有比这种糟糕的嵌套if语句更好的设计

编辑:意识到我的示例代码过于简单。下面是我的一段真实代码,希望它能更好地解释这个问题(尽管它要复杂得多):

if(!diamondsOnly.empty()&&!clubsOnly.empty())
{
if(diamondsOnly.size()clubsOnly.back().value)
{
如果(通过HighCards(player.hand,getHighCards(卡片:钻石),结果))
返回结果;
if(通过高卡(玩家手牌,获得高卡(卡::俱乐部),结果))
返回结果;
}
其他的
{
if(通过高卡(玩家手牌,获得高卡(卡::俱乐部),结果))
返回结果;
如果(通过HighCards(player.hand,getHighCards(卡片:钻石),结果))
返回结果;
}
}
}
else如果(!diamondsOnly.empty())
{
如果(通过HighCards(player.hand,getHighCards(卡片:钻石),结果))
返回结果;
}
如果(!clubsOnly.empty())
{
if(通过高卡(玩家手牌,获得高卡(卡::俱乐部),结果))
返回结果;
}

我不确定这是否是一个巨大的改进,但您可以通过以下方法稍微消除毛茸茸的感觉:

if (thing1.empty() && thing2.empty())
   return func4();
else if (thing1.empty())
    return func2();
else if (thing2.empty())
    return func1();
else if (thing1.property < thing2.property)
    return func1();
else if (thing2.property < thing1.property)
    return func2();
else
    return func3();
然后,当您涵盖了所有条件后,执行一个简单的循环来做正确的事情

for (int i = 0; i < 2; i++)
{
    if (pass[i] != -1 && passHighCards(player.hand, getHighCards(pass[i]), result))
        return result;
}

...undocumented what happens here...
for(int i=0;i<2;i++)
{
如果(通过[i]!=-1&&PasshHighCards(player.hand,getHighCards(通过[i]),结果))
返回结果;
}
…这里发生的事没有记录。。。
二是轻度不适;它出现了两次


但是,总的来说,这为您提供了一个线性的测试序列,每个测试之后都有简单的对称动作(为了一致性,这次保留了大括号,因为动作不止一行长;一致性比大括号本身的存在或不存在更重要)。当关于做什么的决定完成后,你实际上就去做了。

创建一个界面,比如说IMyCompare。 使用接受IMyCompare并返回Func的方法 然后你可以在每件事情上实现整个事情

做 类似于AThing.MyCompare(其他事物)

如果每个条件中的哪个函数不是由对象的类型确定的,那么将函数数组传递给比较调用


我很想从MyCompare返回一个int,并将如何使用它的问题委托给我认为是其他问题。

您可以计算所有条件并将它们发送给某个函数,该函数应该执行决策,然后返回一个代码,告诉下一步该做什么。然后,所有重复的“模式”都将位于函数内部

// return decision1 or decision2, depending on the result of comparison of properties
// Note: type is ssize_t to accommodate bool, size_t and whatever type is 'value'
int decision(ssize_t property1, ssize_t property2, int decision1, int decision2)
{
    if (property1 > property2)
        return decision1;
    else if (property2 > property1)
        return decision2;
    else
        return 0;
}

some_func()
{
    int decision = decide(!diamondsOnly.empty(), !clubsOnly.empty(), 1, 2);
    if (!decision)
        decision = decide(diamondsOnly.size(), clubsOnly.size(), 3, 4);
    if (!decision)
        decision = decide(diamondsOnly.back().value, clubsOnly.back().value, 3, 4);

    bool flag;
    switch (decision)
    {
        case 1:
            flag = passHighCards(player.hand, getHighCards(Card::DIAMONDS), result);
            break;
        case 2:
            flag = passHighCards(player.hand, getHighCards(Card::CLUBS), result);
            break;
        case 3:
            flag = passHighCards(player.hand, getHighCards(Card::DIAMONDS), result);
            flag = passHighCards(player.hand, getHighCards(Card::CLUBS), result);
            break;
        case 4:
            flag = passHighCards(player.hand, getHighCards(Card::CLUBS), result);
            flag = passHighCards(player.hand, getHighCards(Card::DIAMONDS), result);
            break;
        default:
            flag = whatever();
            break;
    }

    if (flag)
        return result;
}

在上面的代码中,
开关
语句违反了DRY;如果您认为这仍然是一个问题,您可以使用“聪明”代码,将动作编码为各自的位:

  • 第0位:是否要做任何事情
  • 第一位:首先做什么
  • 第二点:是否做第二件事
  • 比特3:下一步该怎么办


然而,在我看来,这件“干兼容”的衣服看起来比开关更毛茸茸的

看一下真正的代码,我注意到的第一件事是,有很多几乎相同的调用,它们只按常量变化。我将使用复杂逻辑中设置的参数在一个地方进行调用

// 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;
}
//决定做什么。
std::向量通序;
如果(!diamondsOnly.empty()&&!clubsOnly.empty()){
//..复杂的逻辑为Passworder增加了适合性。。
}
//去做吧。
对于(auto-suit:passOrder){//这是C++11样式——根据需要进行更改
if(通过高牌(玩家手牌,获得高牌(套装),结果))
返回结果;
}
(如果向量总是一个或两个,那么使用向量可能会有点过头,但我假设真正的代码可能会处理所有的诉讼。)

这使它更容易阅读。程序员可以看到,首先你决定传递卡片的顺序,然后你实际传递卡片。两个独立的步骤将会更加清晰。只有一个称为Passcard的地方比在整个决策逻辑中分散使用Passcard的副本更不容易出现愚蠢的打字错误。它还将使调试变得更容易,因为您可以在非常特定的情况下设置断点,或者您可以在循环的开始处设置断点并检查passOrder

简化逻辑

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

选项:

  • 哨兵:部分复杂原因是,在某些情况下,您需要取消对其中一个容器中最后一张卡的引用,这可能是错误的
    // return decision1 or decision2, depending on the result of comparison of properties
    // Note: type is ssize_t to accommodate bool, size_t and whatever type is 'value'
    int decision(ssize_t property1, ssize_t property2, int decision1, int decision2)
    {
        if (property1 > property2)
            return decision1;
        else if (property2 > property1)
            return decision2;
        else
            return 0;
    }
    
    some_func()
    {
        int decision = decide(!diamondsOnly.empty(), !clubsOnly.empty(), 1, 2);
        if (!decision)
            decision = decide(diamondsOnly.size(), clubsOnly.size(), 3, 4);
        if (!decision)
            decision = decide(diamondsOnly.back().value, clubsOnly.back().value, 3, 4);
    
        bool flag;
        switch (decision)
        {
            case 1:
                flag = passHighCards(player.hand, getHighCards(Card::DIAMONDS), result);
                break;
            case 2:
                flag = passHighCards(player.hand, getHighCards(Card::CLUBS), result);
                break;
            case 3:
                flag = passHighCards(player.hand, getHighCards(Card::DIAMONDS), result);
                flag = passHighCards(player.hand, getHighCards(Card::CLUBS), result);
                break;
            case 4:
                flag = passHighCards(player.hand, getHighCards(Card::CLUBS), result);
                flag = passHighCards(player.hand, getHighCards(Card::DIAMONDS), result);
                break;
            default:
                flag = whatever();
                break;
        }
    
        if (flag)
            return result;
    }
    
    if ((decision & 1) == 0) {flag = whatever;}
    else
    {
        thing1 = (decision & 2) ? Card::DIAMONDS : Card::CLUBS
        flag = passHighCards(player.hand, thing1, result);
        if (decision & 4)
        {
            thing2 = (decision & 8) ? Card::DIAMONDS : Card::CLUBS;
            flag = passHighCards(player.hand, thing2, 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;
    }
    
    // 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;
    }