Le moyen le plus simple de retourner une valeur booléenne?


124

Je veux juste retourner un booléen basé sur ce qu'il est déjà. Si c'est vrai, faites-le faux. Si c'est faux, rendez-le vrai.

Voici mon extrait de code:

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

Réponses:


341

Vous pouvez inverser une valeur comme ceci:

myVal = !myVal;

donc votre code se réduirait à:

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

    case VK_F12:
    otherVal = !otherVal;
    break;

    default:
    break;
}

7
C'est non seulement le moyen le plus simple, mais aussi le plus propre.
sharptooth

les deux cas peuvent être fusionnés car ils font la même chose.
David Allan Finch

1
Est la valeur par défaut: break; vraiment nécessaire? Le commutateur ne se terminera-t-il pas de la même manière sans lui?
Chris Lutz

12
Par défaut: break; est inutile.
Rob K

4
Si vous basculez quelque chose de long comme object1-> system1.system2.system3.parameter1, alors il peut être utile d'avoir une macro TOGGLE (a). Cela évite certaines erreurs et rend le tout plus lisible sur des écrans étroits.
OJW

77

Vous avez clairement besoin d'un modèle d'usine!

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

:RÉ

</sarcasm>

9
Nous pourrions probablement ajouter le modèle de singleton pour l'usine aussi.
Drew

@Orm Parce que tu es un ORM ? :)
mlvljr

3
Notez la recommandation subtile de passer à Java!
Escargot mécanique

Eh bien ... je pense que nous avons besoin d'une autre version majeure de C ++ pour celui-ci, peut-être C ++ / 51
0x6900

Salut les gars! Je pense que votre approche n'est pas réentrante. Vous avez besoin d'au moins atomic_bool, mieux un mutex ou une file d'attente d'événements. De plus, nous avons besoin d'un modèle d'observateur pour surveiller l'état de val.
Marco Freudenberger

38

Si vous savez que les valeurs sont 0 ou 1, vous pouvez le faire flipval ^= 1.


1
Pourquoi utiliser un opérateur binaire pour une opération logique? Des odeurs d'obscurcissement inutile pour moi.
Mark Pim

5
@Mark: Désolé. Je suppose que je suis démodé. Mais cela aide si votre expression de valeur L est vraiment longue, vous n'avez donc pas à la répéter. Vous pouvez également dire flipval ^ = TRUE. Est-ce mieux?
Mike Dunlavey

6
@Alnitak: Vous avez raison dans certaines circonstances. J'ai vu des gens emballer des morceaux ensemble pour "économiser de l'espace" et agir comme si les instructions pour y accéder ne prenaient pas de place.
Mike Dunlavey

2
@Albert: ^est l' opérateur exclusif-or . 0^1est 1, et 1^1est 0. C'est la même chose que d'ajouter si vous ignorez le bit de retenue. Ou vous pouvez le considérer comme - si l'un des bits est 1, le résultat est l'inverse de l'autre bit. Ou vous pouvez penser que cela pose la question: ces deux éléments sont-ils différents?
Mike Dunlavey

1
@MikeDunlavey si vous êtes sur un appareil avec 4M de Flash pour l'espace de code et 3K de SRAM pour l'espace de données, alors c'est une manière justifiée d'agir!
MM

33

La solution la plus simple que j'ai trouvée:

x ^= true;

11
x = !x;est non seulement plus court, mais aussi plus lisible.
Rodrigo

13
Notez que par exemple longVariableName ^= true;est clairement plus court que longVariableName = !longVariableName;Et chaque programmeur doit connaître XOR.
xamid

a ^= bsignifie a = a ^ b, où ^signifie XOR. La notation a °= bpour a = a ° bn'importe quel opérateur °est très courante dans la syntaxe C / C ++ / C #.
xamid

2
Anecdotique, mais je suis récemment tombé sur la ligne gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value = !gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value;Bien sûr, la chose la plus propre à faire est de l'étendre à plusieurs lignes et d'utiliser des variables temporaires pour stocker les objets, mais elle gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value ^= 1est beaucoup plus lisible, moins sujette aux erreurs et moins de caractères que le code d'origine .
Vortico du

1
De plus, moins de duplication signifie moins de chances d'oublier de mettre à jour les DEUX côtés de l'équation lors de changements de développement rapides / de longues journées / nuits de codage.
Katastic Voyage

11

Juste pour information - si au lieu d'un entier, votre champ obligatoire est un seul bit dans un type plus grand, utilisez plutôt l'opérateur '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

Cela semble être un free-for-all ... Heh. Voici une autre variation, qui, je suppose, est plus dans la catégorie «intelligente» que quelque chose que je recommanderais pour le code de production:

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

Je suppose que ses avantages sont:

  • Très concis
  • Ne nécessite pas de branchement

Et un inconvénient tout aussi évident est

  • Très concis

Ceci est proche de la solution de @ korona utilisant?: Mais fait un (petit) pas plus loin.


2
Par ordre d'opérations, je pense que vous pouvez omettre la parenthèse pour encore plus de concision. : O
Match

8

Juste parce que ma manière préférée de faire basculer un booléen n'est pas répertoriée ...

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

fonctionne aussi. :)

(oui x = !x;c'est plus clair et plus facile à lire)


6

La solution codegolf'ish serait plus comme:

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

2

Je préfère la solution de John T, mais si vous voulez passer au code-golfy, votre déclaration se réduit logiquement à ceci:

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

Vous n'avez pas à vérifier wParam par rapport à VK_F11 et VK_F12?
drby


0

Il est clair que vous avez besoin d'une solution flexible capable de prendre en charge les types se faisant passer pour des booléens. Ce qui suit permet cela:

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

Vous pouvez ensuite le spécialiser pour différents types qui pourraient prétendre être booléens. Par exemple:

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

Un exemple d'utilisation de cette construction:

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

Non, je ne suis pas sérieux.


0

Pour les entiers avec des valeurs de 0 et 1, vous pouvez essayer:

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

Juste parce que j'aime remettre en question le code. Je propose que vous puissiez également utiliser le ternaire en faisant quelque chose comme ceci:

Exemple:

bool flipValue = false;
bool bShouldFlip = true;
flipValue = bShouldFlip ? !flipValue : flipValue;
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.