翻转布尔值的最简单方法?

Easiest way to flip a boolean value?

提问人: 提问时间:3/4/2009 最后编辑:5 revs, 4 users 96%John T 更新时间:2/24/2020 访问量:303864

问:

我只想根据它已经是什么来翻转布尔值。如果它是真的 - 让它成为假的。如果它是假的 - 让它成为真的。

这是我的代码摘录:

switch(wParam) {

case VK_F11:
  if (flipVal == true) {
     flipVal = false;
  } else {
    flipVal = true;
  }
break;

case VK_F12:
  if (otherVal == true) {
     otherValVal = false;
  } else {
    otherVal = true;
  }
break;

default:
break;
}
C++ C 布尔逻辑

评论


答:

412赞 3 revs, 3 users 79%John T #1

您可以像这样翻转值:

myVal = !myVal;

因此,您的代码将缩短为:

switch(wParam) {
    case VK_F11:
    flipVal = !flipVal;
    break;

    case VK_F12:
    otherVal = !otherVal;
    break;

    default:
    break;
}

评论

13赞 sharptooth 3/4/2009
这不仅是最简单的,也是最干净的方法。
0赞 David Allan Finch 3/4/2009
这两种情况可以合并,因为它们做同样的事情。
1赞 Chris Lutz 3/6/2009
默认值:break;真的有必要吗?没有它,开关的结局不会一样吗?
14赞 Rob K 3/6/2009
默认值:break;是不必要的。
4赞 OJW 10/1/2010
如果您要切换诸如 object1->system1.system2.system3.parameter1 之类的冗长内容,那么使用 TOGGLE(a) 宏会很有帮助。这样可以防止一些错误,并使它在窄屏幕上更具可读性。
2赞 JosephStyons 3/4/2009 #2

我更喜欢 John T 的解决方案,但如果你想去所有的代码,你的陈述在逻辑上可以简化为:

//if key is down, toggle the boolean, else leave it alone.
flipVal = ((wParam==VK_F11) && !flipVal) || (!(wParam==VK_F11) && flipVal);
if(wParam==VK_F11) Break;

//if key is down, toggle the boolean, else leave it alone.
otherVal = ((wParam==VK_F12) && !otherVal) || (!(wParam==VK_F12) && otherVal);
if(wParam==VK_F12) Break;

评论

0赞 drby 3/4/2009
难道您不必将 wParam 与 VK_F11 和 VK_F12 进行对比吗?
9赞 korona 3/5/2009 #3

codegolf'ish 解决方案更像是:

flipVal = (wParam == VK_F11) ? !flipVal : flipVal;
otherVal = (wParam == VK_F12) ? !otherVal : otherVal;
46赞 Mike Dunlavey 3/5/2009 #4

如果您知道值为 0 或 1,则可以执行 .flipval ^= 1

评论

1赞 Mark Pim 3/5/2009
为什么要使用按位运算符进行逻辑运算?对我来说,闻起来有不必要的混淆。
6赞 Mike Dunlavey 3/5/2009
@Mark:对不起。猜猜我是老式的。但是,如果您的 L 值表达式真的很长,它确实会有所帮助,因此您不必重复它。另外,你可以说flipval ^= TRUE。这样会更好吗?
6赞 Mike Dunlavey 3/6/2009
@Alnitak:在某些情况下,你是对的。我见过一些人为了“节省空间”而将位打包在一起,并表现得好像访问它们的指令不占用任何空间。
2赞 Mike Dunlavey 11/12/2013
@Albert:是排他性或运算符。 是 ,并且是 。这与忽略进位时添加相同。或者你可以把它想象成 - 如果任一位是 1,则结果是另一位的倒数。或者你可以把它想象成问一个问题:这两个位不同吗?^0^111^10
1赞 M.M 12/16/2014
@MikeDunlavey,如果您使用的设备具有 4M 闪存作为代码空间,3K SRAM 用于数据空间,那么这是一种合理的行为方式!
98赞 Drew 3/5/2009 #5

显然,你需要一个工厂模式!

KeyFactory keyFactory = new KeyFactory();
KeyObj keyObj = keyFactory.getKeyObj(wParam);
keyObj.doStuff();


class VK_F11 extends KeyObj {
   boolean val;
   public void doStuff() {
      val = !val;
   }
}

class VK_F12 extends KeyObj {
   boolean val;
   public void doStuff() {
      val = !val;
   }
}

class KeyFactory {
   public KeyObj getKeyObj(int param) {
      switch(param) {
         case VK_F11:
            return new VK_F11();
         case VK_F12:
            return new VK_F12();
      }
      throw new KeyNotFoundException("Key " + param + " was not found!");
   }
}

:D

</sarcasm>

评论

16赞 Drew 3/5/2009
我们可能也可以为工厂添加单例模式。
1赞 mlvljr 3/20/2010
@Orm 因为你是ORM?:)
7赞 Mechanical snail 12/20/2012
请注意切换到 Java 的微妙建议!
1赞 0x6900 9/15/2015
井。。。我认为我们需要另一个主要的C++版本,可能是C++/51
3赞 Casey 5/4/2020
我不确定这是惊人的还是可怕的......可能很神奇。给初学者的提示:事实上,德鲁是在讽刺。您应该选择尽可能简单(但不更简单)的解决方案......虽然工厂模式很强大,你应该学习它。</不是讽刺>
17赞 Alnitak 3/5/2009 #6

仅供参考 - 如果必填字段不是整数,而是较大类型中的单个位,请改用“xor”运算符:

int flags;

int flag_a = 0x01;
int flag_b = 0x02;
int flag_c = 0x04;

/* I want to flip 'flag_b' without touching 'flag_a' or 'flag_c' */
flags ^= flag_b;

/* I want to set 'flag_b' */
flags |= flag_b;

/* I want to clear (or 'reset') 'flag_b' */
flags &= ~flag_b;

/* I want to test 'flag_b' */
bool b_is_set = (flags & flag_b) != 0;
1赞 dma 3/5/2009 #7

显然,您需要一个灵活的解决方案,该解决方案可以支持伪装成布尔值的类型。以下允许这样做:

template<typename T>    bool Flip(const T& t);

然后,您可以将其专门用于可能假装为布尔值的不同类型。例如:

template<>  bool Flip<bool>(const bool& b)  { return !b; }
template<>  bool Flip<int>(const int& i)    { return !(i == 0); }

使用此构造的示例:

if(Flip(false))  { printf("flipped false\n"); }
if(!Flip(true))  { printf("flipped true\n"); }

if(Flip(0))  { printf("flipped 0\n"); }
if(!Flip(1)) { printf("flipped 1\n"); }

不,我不是认真的。

10赞 unwind 3/5/2009 #8

这似乎是一个免费的......嘿。这是另一个变体,我想它更像是“聪明”的类别,而不是我推荐用于生产代码的东西:

flipVal ^= (wParam == VK_F11);
otherVal ^= (wParam == VK_F12);

我想它的优点是:

  • 非常简洁
  • 不需要分支

一个同样明显的缺点是

  • 非常简洁

这接近于@korona使用 ?: 的解决方案,但又向前迈进了一小步。

评论

3赞 Drew 9/29/2011
按照操作顺序,我认为您可以省略括号以使其更简洁。:O
12赞 Rozwel #9

仅仅因为我最喜欢的奇怪的球切换布尔值的方式没有列出......

bool x = true;
x = x == false;

也有效。:)

(是的,更清晰,更易于阅读)x = !x;

3赞 evandrix #10
flipVal ^= 1;

同样如此

otherVal
55赞 xamid #11

我发现的最简单的解决方案:

x ^= true;

评论

29赞 Rodrigo 10/4/2017
x = !x;不仅更短,而且更清晰。
32赞 xamid 10/6/2017
请注意,例如 显然比 每个程序员都应该知道 XOR。longVariableName ^= true;longVariableName = !longVariableName;
8赞 Vortico 10/31/2017
轶事,但我最近遇到了这条线 当然,最干净的做法是将其扩展到多行并使用临时变量来存储对象,但与原始代码相比,可读性更强,更不容易出错,字符更少。gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value = !gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value;gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value ^= 1
3赞 Katastic Voyage 11/14/2017
此外,更少的重复意味着在快速开发更改/漫长的日/夜编码期间忘记更新等式两边的机会更少。
1赞 migle 4/30/2020
@Vortico,轶事,但正是为了避免这样的台词,我今天来到这里。我想你可以说冗长也有混淆。
0赞 Artur #12

对于值为 0 和 1 的整数,您可以尝试:

value = abs(value - 1);

C 语言中的 MWE:

#include <stdio.h>
#include <stdlib.h>
int main()
{
        printf("Hello, World!\n");
        int value = 0;
        int i;
        for (i=0; i<10; i++)
        {
                value = abs(value -1);
                printf("%d\n", value);
        }
        return 0;
}
0赞 Jon #13

只是因为我喜欢质疑代码。我建议你也可以通过做这样的事情来利用三元:

例:

bool flipValue = false;
bool bShouldFlip = true;
flipValue = bShouldFlip ? !flipValue : flipValue;