A maneira mais fácil de inverter um valor booleano?


124

Eu só quero virar um booleano com base no que já é. Se é verdade - faça-o falso. Se for falso, faça-o verdadeiro.

Aqui está o meu trecho de código:

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;
}

Respostas:


340

Você pode inverter um valor assim:

myVal = !myVal;

portanto, seu código seria reduzido para:

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

    case VK_F12:
    otherVal = !otherVal;
    break;

    default:
    break;
}

7
Não é apenas a maneira mais fácil, mas também a mais limpa.
Sharptooth 4/03/09

os dois casos podem ser mesclados, pois fazem a mesma coisa.
David Allan Finch

1
É o padrão: break; realmente necessário? O interruptor não terminará o mesmo sem ele?
Chris Lutz

12
Padrão: break; é desnecessário.
Rob K

4
Se você estiver alternando algo de longo prazo como object1-> system1.system2.system3.parameter1, pode ser útil ter uma macro TOGGLE (a). Isso evita alguns erros e torna tudo mais legível em telas estreitas.
OJW

77

Claramente, você precisa de um padrão de fábrica!

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>

9
Provavelmente também poderíamos adicionar o padrão singleton para a fábrica.
Drew

@ Orm Porque você é um ORM ? :)
mlvljr

3
Observe a recomendação sutil de mudar para Java!
Caracol mecânico

Bem ... acho que precisamos de outra versão principal do C ++ para esta, pode ser C ++ / 51
0x6900

Ei pessoal! Eu acho que sua abordagem não é reentrada. Você precisa do atomic_bool, pelo menos, melhor um mutex ou uma fila de eventos. Além disso, precisamos de um padrão de observador para monitorar o estado de val.
Marco Freudenberger

38

Se você souber que os valores são 0 ou 1, é possível flipval ^= 1.


1
Por que usar um operador bit a bit para uma operação lógica? Cheira a ofuscação desnecessária para mim.
Mark Pim #

5
@ Mark: Desculpe. Acho que sou antiquado. Mas ajuda se sua expressão de valor L for realmente longa, para que você não precise repeti-la. Além disso, você pode dizer flipval ^ = TRUE. Isto é melhor?
Mike Dunlavey

6
@ Alnitak: Você está certo em algumas circunstâncias. Eu já vi algumas pessoas juntando bits para "economizar espaço" e agir como se as instruções para acessá-los não ocupassem espaço.
Mike Dunlavey 6/03/09

2
@ Albert: ^é o operador exclusivo ou . 0^1é 1e 1^1é 0. É o mesmo que adicionar se você ignorar o bit de transporte. Ou você pode pensar nisso como - se um dos bits é 1, o resultado é o inverso do outro. Ou você pode pensar nisso como a pergunta: esses dois bits são diferentes?
Mike Dunlavey

1
@ MikeDunlavey se você estiver em um dispositivo com 4 M de Flash para espaço de código e 3 K de SRAM para espaço de dados, essa é uma maneira justificada de agir!
MM

33

Solução mais fácil que encontrei:

x ^= true;

11
x = !x;não é apenas mais curto, mas também mais legível.
Rodrigo

13
Observe que, por exemplo, longVariableName ^= true;é claramente menor que longVariableName = !longVariableName;E todo programador deve conhecer o XOR.
Xamid 5/10

a ^= bsignifica a = a ^ b, onde ^significa XOR. A notação a °= bpara a = a ° bqualquer operador °é muito comum entre a sintaxe C / C ++ / C #.
Xamid 6/10

2
Anedótico, mas me deparei recentemente com a linha gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value = !gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value;Naturalmente, a coisa mais limpa a fazer é expandi-la para várias linhas e usar variáveis ​​temporárias para armazenar os objetos, mas gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value ^= 1é muito mais legível, menos suscetível a erros e menos caracteres do que o código original .
Vortico

1
Além disso, menos duplicação significa menos chance de esquecer de atualizar AMBOS os lados da equação durante mudanças rápidas no desenvolvimento / longos dias / noites de codificação.
Katastic Voyage

11

Apenas para informação - se, em vez de um número inteiro, o campo necessário for um bit único em um tipo maior, use o operador '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;

9

Isso parece ser de graça para todos ... Heh. Aqui está outra variação, que eu acho que é mais na categoria "inteligente" do que algo que eu recomendaria para o código de produção:

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

Eu acho que as vantagens são:

  • Muito conciso
  • Não requer ramificação

E uma desvantagem tão óbvia é

  • Muito conciso

Isso está próximo da solução da @ korona usando?: Mas deu um (pequeno) passo adiante.


2
Por ordem das operações, acho que você pode omitir os parênteses para ficar ainda mais conciso. : O
Drew

8

Só porque minha maneira ímpar favorita de alternar um bool não está listada ...

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

funciona também :)

(sim, x = !x;é mais claro e fácil de ler)


6

A solução codegolf'ish seria mais como:

flipVal = (wParam == VK_F11) ? !flipVal : flipVal;
otherVal = (wParam == VK_F12) ? !otherVal : otherVal;

2

Prefiro a solução de 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;

Você não precisa verificar o wParam no VK_F11 e no VK_F12?
drby


0

Claramente, você precisa de uma solução flexível que suporte tipos disfarçados de booleanos. O seguinte permite isso:

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

Você pode especializar isso para diferentes tipos que podem fingir ser booleanos. Por exemplo:

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

Um exemplo de uso dessa construção:

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"); }

Não, não estou falando sério.


0

Para números inteiros com valores de 0 e 1, você pode tentar:

value = abs(value - 1);

MWE em C:

#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

Só porque eu gosto de questionar o código. Proponho que você também possa fazer uso do ternário fazendo algo assim:

Exemplo:

bool flipValue = false;
bool bShouldFlip = true;
flipValue = bShouldFlip ? !flipValue : flipValue;
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.