Найпростіший спосіб перевернути булеве значення?


124

Я просто хочу перевернути булевий на основі того, що він є. Якщо це правда - зробіть її помилковою. Якщо це неправда - зробіть це правдою.

Ось мій витяг з коду:

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

Відповіді:


341

Ви можете перевернути таке значення, як:

myVal = !myVal;

тож ваш код скоротиться до:

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

    case VK_F12:
    otherVal = !otherVal;
    break;

    default:
    break;
}

7
Це не тільки найпростіший, але і найчистіший спосіб.
гострий зуб

обидва випадки можуть бути об'єднані, оскільки вони роблять те саме.
Девід Аллан Фінч

1
За замовчуванням: перерва; дійсно необхідні? Чи не вимикач закінчиться так само без нього?
Кріс Лутц

12
За замовчуванням: перерва; є непотрібним.
Роб К

4
Якщо ви перемикаєте щось навітряне, наприклад object1-> system1.system2.system3.parameter1, то може бути корисним макрос TOGGLE (a). Це запобігає деяким помилкам і робить його більш читабельним на вузьких екранах.
OJW

77

Очевидно, що вам потрібен заводський зразок!

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
Ми могли б, мабуть, додати в одинарний візерунок і для фабрики.
Дрю

@Orm Причина ти ORM ? :)
mlvljr

3
Зверніть увагу на тонку рекомендацію щодо переходу на Java!
Механічний равлик

Ну ... я думаю, нам потрібен ще один головний випуск C ++ для цього, можливо, це C ++ / 51
0x6900

Гей, хлопці! Я думаю, що ваш підхід не є репрезентом. Вам потрібно щонайменше atomic_bool, краще мютекс або черга подій. Далі нам потрібна схема спостереження для моніторингу стану val.
Марко Фройденбергер

38

Якщо ви знаєте, що значення дорівнюють 0 або 1, ви можете зробити це flipval ^= 1.


1
Навіщо використовувати бітовий оператор для логічної операції? Пахне непотрібним мені опушення.
Марк Пім

5
@ Марк: Вибач. Здогадайтесь, я старомодний. Але це допомагає, якщо вираз L-значення дійсно довгий, тому вам не доведеться повторювати його. Також можна сказати flipval ^ = ІСТИНА. Це краще?
Майк Данлаве

6
@Alnitak: Ти маєш рацію за деяких обставин. Я бачив, як деякі люди збирають біти разом, щоб "заощадити місце" і діяти так, ніби вказівки щодо доступу до них не займають місця.
Майк Данлаве

2
@Albert: ^є ексклюзивним або оператором. 0^1є 1, і 1^1є 0. Це те саме, що додавати, якщо ви ігноруєте переносний біт. Або ви можете подумати про це як - якщо будь-який біт дорівнює 1, результат є зворотним для іншого біта. Або ви можете подумати про це як запитання: Чи відрізняються ці два біти?
Майк Данлаве

1
@MikeDunlavey, якщо ви користуєтесь пристроєм із 4M Flash для кодового простору та 3K SRAM для простору даних, то це виправданий спосіб дії!
ММ

33

Найпростіше рішення, яке я знайшов:

x ^= true;

11
x = !x;є не тільки коротшим, але й більш розбірливим.
Родріго

13
Зауважте, що, наприклад longVariableName ^= true;, явно коротше, ніж longVariableName = !longVariableName;І, кожен програміст повинен знати XOR.
xamid

a ^= bозначає a = a ^ b, де ^означає XOR. Позначення a °= bдля a = a ° bбудь-якого оператора °дуже поширене серед синтаксису C / C ++ / C #.
xamid

2
Анекдотично, але я нещодавно натрапив на рядок. gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value = !gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value;Звичайно, найчистіше, що потрібно зробити, це розширити його на кілька рядків і використовувати тимчасові змінні для зберігання об'єктів, але gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value ^= 1це набагато читабельніше, менше схильних до помилок і менше символів, ніж оригінальний код .
Vortico

1
Крім того, менше дублювання означає менше шансів забути оновити ДІЯННЯ сторони рівняння під час швидких змін розвитку / довгі дні / ночі кодування.
Katastic Voyage

11

Тільки для інформації - якщо замість цілого числа потрібне вам поле є єдиним бітом у великому типі, замість цього скористайтеся оператором '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

Це здається безкоштовним для всіх ... Хе. Ось ще одна варація, яка, напевно, більше відноситься до категорії "розумний", ніж щось, що я б рекомендував у виробничому коді:

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

Я думаю, що його переваги:

  • Дуже лаконічно
  • Не вимагає розгалуження

І так само очевидний недолік

  • Дуже лаконічно

Це близьке до рішення @ korona з використанням?:, Але зроблено ще один (маленький) крок.


2
За порядком операцій, я думаю, ви можете пропустити круглі дужки ще більше. : O
Дрю

8

Тільки тому, що мого улюбленого способу переключення булів не вказано ...

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

працює теж. :)

(так, x = !x;це зрозуміліше і легше читати)


6

Рішення кодегольфа буде більше схоже на:

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

2

Я віддаю перевагу рішенню Джона Т, але якщо ви хочете пройти весь код-гофр, ваше твердження логічно зводиться до цього:

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

Не потрібно перевіряти wParam на VK_F11 та VK_F12?
drby


0

Очевидно, що вам потрібно гнучке рішення, яке може підтримувати типи, що маскуються під булеві. Це дозволяє:

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

Потім ви можете спеціалізувати це на різних типах, які можуть видаватись булевими. Наприклад:

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

Приклад використання цієї конструкції:

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

Ні, я несерйозний.


0

Для цілих чисел зі значеннями 0 та 1 ви можете спробувати:

value = abs(value - 1);

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

Просто тому, що мені подобається запитувати код. Я пропоную вам також скористатися терміналом, зробивши щось подібне:

Приклад:

bool flipValue = false;
bool bShouldFlip = true;
flipValue = bShouldFlip ? !flipValue : flipValue;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.