c++ 如何在bool值(false和true)上编写for循环

piah890a  于 2023-05-02  发布在  其他
关注(0)|答案(9)|浏览(270)

一个主要是为了好玩/好奇的问题:如何在C中编写一个for循环,该循环将迭代bool的两个值(i.即truefalse),仅使用与bool(即truefalse)的运算。即不转换为其他类型)?
背景是,我想检查像(A && B) || (!B && !C && !D) == true这样的方程有多少个解,并开始写像for (bool A=false; ??? ; ++A) for (bool B=false; ...)等的东西,但很快就被???- i卡住了。e.继续循环的条件是什么?当然,我重写了它以使用int,我也知道do ... while循环可以工作,但我很好奇是否有可能编写这样的for循环?既然我不知道答案,我决定问:)
更新:请注意,在至少两个现已删除的答案中建议的“明显”变体for(bool A=false; !A; A=true)将只运行一次迭代,因为对于第二个,条件!A变为false,循环结束。
经过一番思考,我相信在C
03中,如果没有第二个变量或Dietmar Kühl建议的基于指针的构造,就不可能做到这一点。在期望的执行中,条件应该被测试三次,所以两个bool值是不够的。do-while循环之所以有效,是因为第一次迭代是无条件执行的,条件只检查两次,因此可以使用bool值来选择继续还是退出。

vi4fp9gy

vi4fp9gy1#

在C11中:for (bool b : { false, true }) { /* ... */ }
下面是C
03版本:

for (bool a = true, b = false; b != a; a = a && b, b = !b) { /*...*/ }

(Use ab。)

zynd9foi

zynd9foi2#

当局限于C2003时,你可以使用一种大致等同于C2011的方法;

{
  bool const bools[] = { false, true };
  for (bool const* it(bools); it != std::end(bools); ++it) {
      bool a(*it);
      use(a);
  }
}

可能被打包进了一个宏。您还可以使用

for (bool a: { false, true }) {
    use(a);
}
h5qlskok

h5qlskok3#

for (int a = 0; a <= 1; a++)
  doStuff(a ? true : false);

忘记“没有转换到其他类型”的限制:)在一天结束时,清晰度比人为的限制更重要。五年后,你会阅读自己的代码,想知道“我到底在想什么,这是某种混淆比赛吗?”“

t9eec4r0

t9eec4r04#

a = true;
do {
  use(a);
  a = !a;
} while (!a);

好吧,所以它不是一个 for 循环,但我认为它比任何for循环建议(当然,除了C++11方法)更具可读性。)

wj8zmpe1

wj8zmpe15#

C++03:

for(bool a = false, b = true; b; a = !a, b = a)

使用B。

hc8w905p

hc8w905p6#

这个答案解决了“不可能的”C++03,单变量的唯一解决方案
首先,让我们确认,没有一个仅依赖于单个输入变量的确定性算术表达式对于两个输入true,false都是真的,但对于必须是truefalse之一的第三个值则不是真的。
但是,我们可以“作弊”。不过,我恳求你证明我真的在作弊。

#include <iostream>

using namespace std;

int main() {
    for (bool b = false; *((char*)&b) != 2; *((char*)&b) += 1) {
        cout << "bool " << b << endl;
    }
}

这看起来像是一种未定义的行为。C++03是位unclear about it。但是,sizeof必须始终至少为1(对于长度为0的可变长度数组,有一个非标准的例外)。此外,由于我们保证每个字符至少是8位,因此我们可以使用第二个字符作为计数器。
实际上,要做到这一点,我们需要避开确定性(如果不放弃对false, true只迭代一次的保证,就不能这样做),或者我们的约束类型系统。

af7jpaap

af7jpaap7#

这个也可以用:

for (bool a = false, b = false; a == b; b = !b, a = a || b) { }

(sort比@KerrekSB的倒置溶液)

wgeznvg7

wgeznvg78#

我知道你要求一个不转换到其他类型的解决方案,但我想你的意思是“不转换到不适当的其他类型”。这里有一个答案,在这个特定的例子中,它提供了一个对象来替换bool

struct IterableBool
{
  bool b;
  bool out_of_scope;
  IterableBool() : b(false), out_of_scope(false) {}
  IterableBool(bool b_) : b(b_), out_of_scope(false) {}
  IterableBool(IterableBool ib) : b(ib.b), out_of_scope(ib.out_of_scope) {}
  operator bool () { return this->b; }
  bool in_scope() const { return !this->out_of_scope; }
  IterableBool& operator ++ ()
  {                    
    this->out_of_scope = this->b;
    this->b = true;
    return *this;
  }
  IterableBool operator ++ (int)
  {
    IterableBool copy = *this;
    ++(*this);
    return copy;
  }
  IterableBool& operator -- ()
  {
    this->out_of_scope = !this->b;
    this->b = false;
    return *this;
  }
  IterableBool operator -- (int)
  {
    IterableBool copy = *this;
    --(*this);
    return copy;
  }
};

// Usage :
for(IterableBool ib = false;  ib.in_scope(); ++ib)
  do_stuff((bool)ib);
qhhrdooz

qhhrdooz9#

一个可能不那么令人困惑的版本,基于Pokrovsky的回答:

bool firstPass=true;
for (int i = 0; i < 2; i++, firstPass=false)
    myfunc(firstPass);

或者更简单地说:

for (int pass = 1; i < 3; i++)
    myfunc(pass == 1);

甚至

for (int secondPass = 0; secondPass < 2; ++secondPass)
    myfunc(!secondPass);

(Pokrovsky的答案优化)。
我认为当程序员在循环中看到变量时,让它有意义是很重要的。

相关问题