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;
}
John T
la source

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;
}
John T
la source
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>
A dessiné
la source
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.

Mike Dunlavey
la source
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;
xamide
la source
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;
Alnitak
la source
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.

se détendre
la source
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)

Rozwel
la source
6

La solution codegolf'ish serait plus comme:

flipVal = (wParam == VK_F11) ? !flipVal : flipVal;
otherVal = (wParam == VK_F12) ? !otherVal : otherVal;
Korona
la source
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;
JosephStyons
la source
Vous n'avez pas à vérifier wParam par rapport à VK_F11 et VK_F12?
drby
2
flipVal ^= 1;

de même pour

otherVal
Evandrix
la source
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.

dma
la source
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;
}
Artur
la source
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;
Jon Black
la source