¿La forma más fácil de voltear un valor booleano?


124

Solo quiero voltear un booleano basado en lo que ya es. Si es verdad, hazlo falso. Si es falso, hazlo verdadero.

Aquí está mi extracto 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;
}

Respuestas:


341

Puede voltear un valor así:

myVal = !myVal;

entonces su código se acortaría a:

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

    case VK_F12:
    otherVal = !otherVal;
    break;

    default:
    break;
}

77
No solo esta es la forma más fácil, sino también la más limpia.
Sharptooth

los dos casos pueden fusionarse ya que hacen lo mismo.
David Allan Finch el

1
Es el valor predeterminado: descanso; ¿realmente necesario? ¿El interruptor no terminará igual sin él?
Chris Lutz

12
Predeterminado: descanso; es innecesario
Rob K

44
Si está alternando algo de largo aliento como object1-> system1.system2.system3.parameter1, puede ser útil tener una macro TOGGLE (a). Esto evita algunos errores y lo hace más legible en pantallas estrechas.
OJW

77

¡Claramente necesitas un patrón 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!");
   }
}

:RE

</sarcasm>

9
Probablemente también podríamos agregar el patrón singleton para la fábrica.
Drew

@Orm Porque eres un ORM ? :)
mlvljr

3
¡Tenga en cuenta la sutil recomendación de cambiar a Java!
Caracol mecánico

Bueno ... creo que necesitamos otro lanzamiento importante de C ++ para este, puede ser C ++ / 51
0x6900

¡Hola chicos! Creo que su enfoque no es reentrante. Necesita al menos atomic_bool, mejor un mutex o una cola de eventos. Además, necesitamos un patrón observador para monitorear el estado de val.
Marco Freudenberger

38

Si sabe que los valores son 0 o 1, podría hacerlo flipval ^= 1.


1
¿Por qué usar un operador bit a bit para una operación lógica? Huele a ofuscación innecesaria para mí.
Mark Pim

55
@ Mark: Lo siento. Supongo que estoy pasado de moda. Pero ayuda si su expresión de valor L es realmente larga, por lo que no tiene que repetirla. Además, podría decir flipval ^ = TRUE. ¿Eso está mejor?
Mike Dunlavey el

66
@Alnitak: Tienes razón en algunas circunstancias. He visto a algunas personas empacar partes para "ahorrar espacio" y actuar como si las instrucciones para acceder a ellas no ocuparan espacio.
Mike Dunlavey el

2
@ Albert: ^es el operador exclusivo . 0^1es 1, y 1^1es 0. Es lo mismo que agregar si ignoras el bit de acarreo. O puede pensarlo como: si un bit es 1, el resultado es el inverso del otro bit. O puede pensar que se trata de hacer la pregunta: ¿Son estos dos bits diferentes?
Mike Dunlavey

1
@MikeDunlavey si estás en un dispositivo con 4M de Flash para espacio de código y 3K de SRAM para espacio de datos, ¡esa es una forma justificada de actuar!
MM

33

La solución más fácil que encontré:

x ^= true;

11
x = !x;No solo es más corto, sino también más legible.
Rodrigo

13
Tenga en cuenta que, por ejemplo, longVariableName ^= true;es claramente más corto que longVariableName = !longVariableName;Y cada programador debe saber XOR.
xamid

a ^= bsignifica a = a ^ b, donde ^significa XOR. La notación a °= bpara a = a ° bcualquier operador °es muy común entre la sintaxis C / C ++ / C #.
xamid

2
Anecdótico, pero recientemente me encontré con la línea. gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value = !gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value;Por supuesto, lo más limpio es expandirlo a varias líneas y usar variables temporales para almacenar los objetos, pero gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value ^= 1es mucho más legible, menos propenso a errores y menos caracteres que el código original. .
Vortico

1
Además, menos duplicación significa menos posibilidades de olvidarse de actualizar AMBOS lados de la ecuación durante los cambios rápidos de desarrollo / días largos / noches de codificación.
Katastic Voyage

11

Solo para información: si en lugar de un número entero su campo requerido es un solo bit dentro de un tipo más grande, use el operador 'xor' en su lugar:

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

Esto parece ser un juego para todos ... Je. Aquí hay otra vacación, que supongo que está más en la categoría "inteligente" que algo que recomendaría para el código de producción:

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

Supongo que sus ventajas son:

  • Muy conciso
  • No requiere ramificación

Y una desventaja igual de obvia es

  • Muy conciso

Esto está cerca de la solución de @ korona usando?: Pero dado un paso (pequeño) más allá.


2
Por orden de operaciones, creo que puede omitir el paréntesis para ser aún más conciso. : O
Drew

8

Solo porque mi forma favorita de alternar una bola no está en la lista ...

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

también funciona :)

(sí, x = !x;es más claro y más fácil de leer)


6

La solución codegolf'ish sería más como:

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

2

Prefiero la solución de John T, pero si quieres ir a todo golf, tu declaración se reduce lógicamente a esto:

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

¿No tienes que verificar wParam contra VK_F11 y VK_F12?
drby


0

Claramente, necesita una solución flexible que pueda admitir tipos enmascarados como booleanos. Lo siguiente permite eso:

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

Luego puede especializar esto para diferentes tipos que pueden pretender ser booleanos. Por ejemplo:

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

Un ejemplo de uso de esta construcción:

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

No, no hablo en serio.


0

Para enteros con valores de 0 y 1 puede intentar:

value = abs(value - 1);

MWE en 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

Solo porque me gusta cuestionar el código. Propongo que también puede hacer uso del ternario haciendo algo como esto:

Ejemplo:

bool flipValue = false;
bool bShouldFlip = true;
flipValue = bShouldFlip ? !flipValue : flipValue;
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.