Python 是否有一个相当于;对于否则";C++;?

Python 是否有一个相当于;对于否则";C++;?,python,c++,loops,for-loop,break,Python,C++,Loops,For Loop,Break,Python有一个有趣的for语句,它允许您指定else子句 在这样的构造中: for i in foo: if bar(i): break else: baz() else子句在for的之后执行,但只有当for的正常终止时(而不是通过中断) 我想知道C++中是否有等价物?我可以用来。。。else?这是我在C++中的粗略实现: bool other = true; for (int i = 0; i > foo; i++) { if (bar[i] == 7)

Python有一个有趣的
for
语句,它允许您指定
else
子句

在这样的构造中:

for i in foo:
  if bar(i):
    break
else:
  baz()
else
子句在for的
之后执行,但只有当for
正常终止时(而不是通过
中断


我想知道C++中是否有等价物?我可以用
来。。。else

这是我在C++中的粗略实现:

bool other = true;
for (int i = 0; i > foo; i++) {
     if (bar[i] == 7) {
          other = false;
          break;
     }
} if(other)
     baz();

是的,您可以通过以下方式实现相同的效果:

auto it = std::begin(foo);
for (; it != std::end(foo); ++it)
     if(bar(*it))
         break;
if(it == std::end(foo))
    baz();
比如:

auto it = foo.begin(), end = foo.end();
while ( it != end && ! bar( *it ) ) {
    ++ it;
}
if ( it != foo.end() ) {
    baz();
}

应该可以做到这一点,它避免了非结构化的
中断

如果不介意使用
goto
也可以通过以下方式完成。这一个保存了额外的
if
check和更高范围的变量声明

for(int i = 0; i < foo; i++)
     if(bar(i))
         goto m_label;
baz();

m_label:
...
for(inti=0;i
表达实际逻辑的更简单方法是:

如果C++17的范围建议被接受,希望这将简化为:

if (std::none_of(foo, bar)) baz();

<> P> C++中没有这样的语言构造,但是,由于预处理器的“魔力”,你可以自己做一个。例如,类似这样的内容(C++11):

然后使用:

FOR_EACH(x, v, {
    if (*x == 2) {
        break;
    }        
    cout << "x = " << *x << " ";
},
else {
    cout << "else";
})
每个(x,v{
如果(*x==2){
打破
}        

cout我不知道有什么优雅的方法可以在C/C++中实现这一点(不涉及标志变量)

为了回答@Kerrek SB关于现实生活中的用法,我在代码中找到了一些(简化的片段)

示例1:典型的查找/失败

for item in elements:
    if condition(item):
        do_stuff(item)
        break
else: #for else
    raise Exception("No valid item in elements")
示例2:尝试次数有限

for retrynum in range(max_retries):
    try:
        attempt_operation()
    except SomeException:
        continue
    else:
        break
else: #for else
    raise Exception("Operation failed {} times".format(max_retries))

您可以为此使用lambda函数:

[&](){
  for (auto i : foo) {
    if (bar(i)) {
      // early return, to skip the "else:" section.
      return;
    }
  }
  // foo is exhausted, with no item satisfying bar(). i.e., "else:"
  baz();
}();
这应该与Python的“for..else”完全相同,并且与其他解决方案相比有一些优势:

  • 这是对“for..else”的真正替换:“for”部分可能有副作用(与none_of不同,none_of的谓词不能修改其参数),并且它可以访问外部范围
  • 它比定义一个特殊的宏更具可读性
  • 它不需要任何特殊的标志变量

但是…我自己会使用笨重的flag变量。

可能没有一个解决方案最适合所有问题。在我的例子中,一个flag变量和一个基于范围的
for
循环以及一个
自动
说明符最有效。下面是一个与所讨论的代码等效的代码:

bool none = true;
for (auto i : foo) {
  if (bar(i)) {
    none = false;
    break;
  }
}
if (none) baz();
它的类型少于。特别是,如果使用
for
循环初始化变量,则可以使用该循环而不是布尔标志

如果您想内联条件而不是调用
bar()
(并且如果您不使用C++14),则由于键入
auto
而比键入更好

我遇到了两种情况,代码如下所示:

for (auto l1 : leaves) {
  for (auto x : vertices) {
    int l2 = -1, y;
    for (auto e : support_edges[x]) {
      if (e.first != l1 && e.second != l1 && e.second != x) {
        std::tie(l2, y) = e;
        break;
      }
    }
    if (l2 == -1) continue;

    // Do stuff using vertices l1, l2, x and y
  }
}
这里不需要迭代器,因为
v
指示是否发生了
break


使用<>代码>::/EngE:<代码> >需要指定λ表达式的参数中的元素。,不仅可以在C++中,也可以在C++中使用C++使代码易于理解:

for (i=foo.first(); i != NULL || (baz(),0); i = i.next())
{
    if bar(i):
        break;
}

我怀疑我是否会让它通过代码审查,但它是有效的。在我看来,它也比其他一些建议更清晰。

直接回答:不,你可能不能,或者它最多是基于编译器的。但这里有一个宏的黑客,这种宏可以工作

请注意:

我通常使用Qt编程,所以我习惯于使用foreach循环,并且从不需要直接处理迭代器

我用Qt的编译器(V5.4.2)对此进行了测试,但它应该可以工作。这很糟糕,有几个原因,但通常可以满足您的要求。我不允许这样编码,但只要您小心语法,它就没有理由不工作

#include <iostream>
#include <vector>

#define for_else(x, y) __broke__ = false; for(x){y} if (__broke__) {}
#define __break__ __broke__ = true; break

bool __broke__;  // A global... wah wah.

class Bacon {
  public:
    Bacon(bool eggs);

    inline bool Eggs() {return eggs_;}

  private:
    bool eggs_;
};

Bacon::Bacon(bool eggs) {
  eggs_ = eggs;
}

bool bar(Bacon *bacon) {
  return bacon->Eggs();
}

void baz() {
  std::cout << "called baz\n";
}

int main()
{
  std::vector<Bacon *>bacons;

  bacons.push_back(new Bacon(false));
  bacons.push_back(new Bacon(false));
  bacons.push_back(new Bacon(false));

  for_else (uint i = 0; i < bacons.size(); i++,
      std::cout << bacons.at(i)->Eggs();
      if (bar(bacons.at(i))) {
        __break__;
      }
  ) else {
    baz();
  }

  bacons.push_back(new Bacon(true));
  bacons.push_back(new Bacon(false));

  for_else (uint i = 0; i < bacons.size(); i++,
      std::cout << bacons.at(i)->Eggs();
      if (bar(bacons.at(i))) {
        __break__;
      }
  ) else {
    baz();
  }

  return EXIT_SUCCESS;
}
#包括
#包括
#为else(x,y)uuu break_uu=false定义;为(x){y}定义if(uuu break_uuu){
#定义“中断”\uuuuuuuuuuuuuuuuuuu中断”\uuuuuuuu=true;中断
bool _; break _;;//一个全球性的……哇哇哇。
培根{
公众:
培根(鸡蛋);
内联bool Eggs(){return Eggs_;}
私人:
鸡蛋;
};
培根:培根(鸡蛋){
蛋=蛋;
}
酒吧(培根*培根){
返回培根->鸡蛋();
}
void baz(){

std::cout通过定义两个宏,您可以使用与Python中几乎相同的其他宏:

#define BREAK {CONTINUETOELSE = false; break;}
#define FORWITHELSE(x, y) {bool CONTINUETOELSE = true; x if(!CONTINUETOELSE){} y}
现在,将
for
else
放在
for WithElse
宏中,用逗号分隔,并使用
BREAK
而不是
BREAK
。下面是一个示例:

FORWITHELSE(
    for(int i = 0; i < foo; i++){
        if(bar(i)){
            BREAK;
        }
    },
    else{
        baz();
    }
)
FORWITHELSE(
for(int i=0;i

有两件事你需要记住:在
else
前面加逗号,用
BREAK
而不是
BREAK
,我来这里是因为我有同样的问题,用C。 我说的最好的事情是

bool notTerminated = true;
for (int i = 0; i < 50 || (notTerminated = false); i++)
    if (bar(i))
        break;
if (! notTerminated)
    baz();
bool notTerminated=true;
for(int i=0;i<50 | |(notTerminated=false);i++)
如果(第(i)条)
打破
如果(!未终止)
baz();

说明:
(notTerminated=false)
是一个始终返回false值的赋值,它永远不会影响条件,如果条件为true,则将在条件为true时进行计算。

我将使用一个简单的辅助变量来完成此操作:

#include <stdio.h>
#include <stdbool.h>

int main()

{
    bool b;
    printf("Numbers which are multiples of 7:\n");

    for (int i=8; b=(i<12); i++)
    {
        if (i%7==0)
        {
            printf("%d", i);
            break;
        }
    }
    if (!b)
    {
        printf("no numbers found\n");
    }
    return 0;
}
#包括
#包括
int main()
{
布尔b;
printf(“7的倍数:\n”);

对于(int i=8;b=(iNote,当Python循环遍历iterable foo的元素时,它从0计数到foo。不过可能很容易调整(与
end()
)相比)。不。Python循环根本不计数。
i
可能永远都不是整数。它更像C++11
for(auto i:foo)
for(自动它=开始(某物);它!=结束(某物);+i)
FORWITHELSE(
    for(int i = 0; i < foo; i++){
        if(bar(i)){
            BREAK;
        }
    },
    else{
        baz();
    }
)
bool notTerminated = true;
for (int i = 0; i < 50 || (notTerminated = false); i++)
    if (bar(i))
        break;
if (! notTerminated)
    baz();
#include <stdio.h>
#include <stdbool.h>

int main()

{
    bool b;
    printf("Numbers which are multiples of 7:\n");

    for (int i=8; b=(i<12); i++)
    {
        if (i%7==0)
        {
            printf("%d", i);
            break;
        }
    }
    if (!b)
    {
        printf("no numbers found\n");
    }
    return 0;
}