Der einfachste Weg, einen Booleschen Wert umzudrehen?

123

Ich möchte nur einen Booleschen Wert umdrehen, basierend auf dem, was er bereits ist. Wenn es wahr ist - mach es falsch. Wenn es falsch ist - mach es wahr.

Hier ist mein Code-Auszug:

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.
quelle

Antworten:

339

Sie können einen Wert wie folgt umdrehen:

myVal = !myVal;

Ihr Code würde sich also verkürzen auf:

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

    case VK_F12:
    otherVal = !otherVal;
    break;

    default:
    break;
}
John T.
quelle
7
Dies ist nicht nur der einfachste, sondern auch der sauberste Weg.
Scharfzahn
Die beiden Fälle können zusammengeführt werden, da sie dasselbe tun.
David Allan Finch
1
Ist Standard: break; wirklich notwendig? Wird der Schalter ohne ihn nicht gleich enden?
Chris Lutz
12
Standard: Pause; ist unnötig.
Rob K
4
Wenn Sie etwas langwieriges wie object1-> system1.system2.system3.parameter1 umschalten, kann es hilfreich sein, ein TOGGLE (a) -Makro zu haben. Dies verhindert einige Fehler und macht alles auf schmalen Bildschirmen besser lesbar.
ABl.
77

Natürlich brauchen Sie ein Fabrikmuster!

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>
Drew
quelle
9
Wir könnten wahrscheinlich auch das Singleton-Muster für die Fabrik hinzufügen.
Drew
@Orm Weil du ein ORM bist ? :)
mlvljr
3
Beachten Sie die subtile Empfehlung, auf Java umzusteigen!
Mechanische Schnecke
Nun ... ich denke, wir brauchen eine weitere Hauptversion von C ++ für diese, möglicherweise C ++ / 51
0x6900
Hallo Leute! Ich denke, Ihr Ansatz ist nicht wiedereintrittsfähig. Sie benötigen mindestens atomic_bool, besser einen Mutex oder eine Ereigniswarteschlange. Ferner benötigen wir ein Beobachtermuster, um den Zustand von val zu überwachen.
Marco Freudenberger
38

Wenn Sie wissen, dass die Werte 0 oder 1 sind, können Sie dies tun flipval ^= 1.

Mike Dunlavey
quelle
1
Warum einen bitweisen Operator für eine logische Operation verwenden? Es riecht nach unnötiger Verschleierung für mich.
Mark Pim
5
@ Mark: Entschuldigung. Ich denke, ich bin altmodisch. Es hilft jedoch, wenn Ihr L-Wert-Ausdruck wirklich lang ist, sodass Sie ihn nicht wiederholen müssen. Man könnte auch flipval ^ = TRUE sagen. Ist das besser?
Mike Dunlavey
6
@Alnitak: Du hast unter bestimmten Umständen Recht. Ich habe einige Leute gesehen, die Bits zusammengepackt haben, um "Platz zu sparen" und so zu tun, als ob die Anweisungen für den Zugriff auf sie keinen Platz beanspruchten.
Mike Dunlavey
2
@ Albert: ^ist der Exklusiv- oder Operator. 0^1ist 1und 1^1ist 0. Dies entspricht dem Hinzufügen, wenn Sie das Übertragsbit ignorieren. Oder Sie können sich das so vorstellen: Wenn eines der Bits 1 ist, ist das Ergebnis die Umkehrung des anderen Bits. Oder Sie können sich vorstellen, die Frage zu stellen: Sind diese beiden Bits unterschiedlich?
Mike Dunlavey
1
@MikeDunlavey Wenn Sie sich auf einem Gerät mit 4 MB Flash für Code-Speicher und 3 KB SRAM für Datenbereich befinden, ist dies eine berechtigte Vorgehensweise!
MM
33

Die einfachste Lösung, die ich gefunden habe:

x ^= true;
Xamid
quelle
11
x = !x;ist nicht nur kürzer, sondern auch besser lesbar.
Rodrigo
13
Beachten Sie, dass zB longVariableName ^= true;deutlich kürzer ist als longVariableName = !longVariableName;Und jeder Programmierer sollte XOR kennen.
Xamid
a ^= bbedeutet a = a ^ b, wo ^bedeutet XOR. Die Notation a °= bfür a = a ° bjeden Operator °ist in der C / C ++ / C # -Syntax sehr verbreitet.
Xamid
2
Anekdotisch, aber ich bin kürzlich auf die Zeile gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value = !gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value;gestoßen. Natürlich ist es am saubersten, sie auf mehrere Zeilen zu erweitern und temporäre Variablen zum Speichern der Objekte zu verwenden. Sie ist jedoch gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value ^= 1viel besser lesbar, weniger fehleranfällig und weniger Zeichen als der ursprüngliche Code .
Vortico
1
Darüber hinaus bedeutet weniger Duplizierung eine geringere Wahrscheinlichkeit, dass vergessen wird, BEIDE Seiten der Gleichung während schneller Entwicklungsänderungen / langer Tage / Nächte der Codierung zu aktualisieren.
Katastic Voyage
11

Nur zur Information - wenn Ihr erforderliches Feld anstelle einer Ganzzahl ein einzelnes Bit innerhalb eines größeren Typs ist, verwenden Sie stattdessen den Operator '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
quelle
9

Dies scheint ein Alleskönner zu sein ... Heh. Hier ist eine weitere Variante, die meiner Meinung nach eher in der Kategorie "clever" liegt als etwas, das ich für den Produktionscode empfehlen würde:

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

Ich denke, die Vorteile sind:

  • Sehr knapp
  • Benötigt keine Verzweigung

Und ein ebenso offensichtlicher Nachteil ist

  • Sehr knapp

Dies kommt der Lösung von @ korona mit ?: Nahe, geht aber noch einen (kleinen) Schritt weiter.

entspannen
quelle
2
Ich denke, Sie können die Klammer in der Reihenfolge der Operationen weglassen, um sie noch knapper zu machen. : O
Drew
8

Nur weil meine Lieblingsmethode zum Umschalten eines Bools nicht aufgeführt ist ...

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

funktioniert auch. :) :)

(ja das x = !x;ist klarer und leichter zu lesen)

Rozwel
quelle
6

Die Codegolf-Lösung wäre eher wie folgt:

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

Ich bevorzuge die Lösung von John T, aber wenn Sie nur Code-Golf spielen möchten, reduziert sich Ihre Aussage logischerweise auf Folgendes:

//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
quelle
Müssen Sie wParam nicht mit VK_F11 und VK_F12 vergleichen?
Drby
2
flipVal ^= 1;

Gleiches gilt für

otherVal
evandrix
quelle
0

Natürlich benötigen Sie eine flexible Lösung, die Typen unterstützt, die sich als boolesch tarnen. Folgendes ermöglicht dies:

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

Sie können dies dann auf verschiedene Typen spezialisieren, die sich als boolesch ausgeben. Beispielsweise:

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

Ein Beispiel für die Verwendung dieses Konstrukts:

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

Nein, ich meine es nicht ernst.

dma
quelle
0

Für ganze Zahlen mit den Werten 0 und 1 können Sie Folgendes versuchen:

value = abs(value - 1);

MWE in 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
quelle
0

Nur weil ich gerne Code frage. Ich schlage vor, dass Sie das Ternäre auch nutzen können, indem Sie so etwas tun:

Beispiel:

bool flipValue = false;
bool bShouldFlip = true;
flipValue = bShouldFlip ? !flipValue : flipValue;
Jon Black
quelle