Cara termudah untuk membalik nilai boolean?


124

Saya hanya ingin membalik boolean berdasarkan apa yang sudah ada. Jika itu benar - buatlah itu salah. Jika itu salah - buatlah itu benar.

Ini kutipan kode saya:

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

Jawaban:


341

Anda dapat membalik nilai seperti ini:

myVal = !myVal;

jadi kode Anda akan dipersingkat menjadi:

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

    case VK_F12:
    otherVal = !otherVal;
    break;

    default:
    break;
}

7
Tidak hanya ini yang termudah, tetapi juga cara terbersih.
gigi tajam

kedua kasus dapat digabungkan karena keduanya melakukan hal yang sama.
David Allan Finch

1
Secara default: istirahat; benar-benar diperlukan? Tidakkah sakelar akan berakhir sama tanpanya?
Chris Lutz

12
Default: istirahat; tidak perlu.
Rob K

4
Jika Anda mengubah sesuatu yang bertele-tele seperti object1-> system1.system2.system3.parameter1 maka akan sangat membantu untuk memiliki makro TOGGLE (a). Ini mencegah beberapa kesalahan dan membuatnya lebih mudah dibaca di layar sempit.
OJW

77

Jelas Anda membutuhkan pola pabrik!

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
Kami mungkin bisa menambahkan pola tunggal untuk pabrik juga.
Mundur

@Orm Penyebab Anda adalah ORM ? :)
mlvljr

3
Perhatikan rekomendasi halus untuk beralih ke Java!
Siput mekanik

Yah ... saya pikir kita perlu rilis utama C ++ lainnya untuk yang ini, mungkin C ++ / 51
0x6900

Hai teman-teman! Saya pikir pendekatan Anda tidak reentrant. Anda memerlukan setidaknya atomic_bool, lebih baik mutex atau antrian acara. Selanjutnya, kita membutuhkan pola pengamat untuk memantau keadaan val.
Marco Freudenberger

38

Jika Anda tahu nilainya 0 atau 1, Anda bisa melakukannya flipval ^= 1.


1
Mengapa menggunakan operator bitwise untuk operasi logis? Bau kebingungan yang tidak perlu bagiku.
Mark Pim

5
@ Mark: Maaf. Sepertinya saya kuno. Tapi itu membantu jika ekspresi nilai-L Anda sangat panjang, jadi Anda tidak perlu mengulanginya. Juga, Anda bisa mengatakan flipval ^ = TRUE. Apakah itu lebih baik?
Mike Dunlavey

6
@ Alnitak: Anda benar dalam beberapa situasi. Saya telah melihat beberapa orang mengemas bit untuk "menghemat ruang" dan bertindak seolah-olah instruksi untuk mengaksesnya tidak memakan tempat.
Mike Dunlavey

2
@Albert: ^adalah operator atau eksklusif . 0^1adalah 1, dan 1^1adalah 0. Ini sama dengan menambahkan jika Anda mengabaikan bit carry. Atau Anda dapat menganggapnya sebagai - jika salah satu bit bernilai 1, hasilnya adalah kebalikan dari bit lainnya. Atau Anda dapat menganggapnya sebagai mengajukan pertanyaan: Apakah kedua bit ini berbeda?
Mike Dunlavey

1
@MikeDunlavey jika Anda menggunakan perangkat dengan Flash 4M untuk ruang kode, dan 3K SRAM untuk ruang data maka itu adalah cara bertindak yang dibenarkan!
MM

33

Solusi termudah yang saya temukan:

x ^= true;

11
x = !x;tidak hanya lebih pendek, tetapi juga lebih terbaca.
Rodrigo

13
Perhatikan bahwa mis longVariableName ^= true;jelas lebih pendek dari longVariableName = !longVariableName;Dan setiap programmer harus tahu XOR.
xamid

a ^= bartinya a = a ^ b, dimana ^berarti XOR. Notasi a °= buntuk a = a ° bsetiap operator °sangat umum di antara sintaks C / C ++ / C #.
xamid

2
Anekdot, tetapi saya baru-baru ini menemukan garis gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value = !gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value;Tentu saja, hal terbersih untuk dilakukan adalah memperluasnya ke beberapa baris dan menggunakan variabel sementara untuk menyimpan objek, tetapi gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value ^= 1jauh lebih mudah dibaca, lebih sedikit rawan kesalahan, dan lebih sedikit karakter daripada kode asli .
Vortico

1
Selain itu, lebih sedikit duplikasi berarti lebih sedikit kesempatan untuk lupa memperbarui KEDUA sisi persamaan selama perubahan perkembangan cepat / hari / malam yang panjang pengkodean.
Katastic Voyage

11

Hanya untuk informasi - jika alih-alih bilangan bulat, bidang wajib Anda adalah satu bit dalam tipe yang lebih besar, gunakan operator 'xor' sebagai gantinya:

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

Sepertinya ini gratis untuk semua ... Heh. Berikut variasi lain, yang menurut saya lebih masuk kategori "pintar" daripada sesuatu yang saya rekomendasikan untuk kode produksi:

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

Saya kira kelebihannya adalah:

  • Sangat singkat
  • Tidak membutuhkan percabangan

Dan kerugian yang sama jelasnya adalah

  • Sangat singkat

Ini mendekati solusi @ korona yang menggunakan?: Tetapi diambil satu langkah (kecil) lebih jauh.


2
Berdasarkan urutan operasi, saya rasa Anda dapat menghilangkan tanda kurung agar lebih ringkas. : O
Mundur

8

Hanya karena cara bola aneh favorit saya untuk beralih bool tidak terdaftar ...

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

bekerja juga. :)

(ya x = !x;lebih jelas dan lebih mudah dibaca)


6

Solusi codegolf'ish akan lebih seperti:

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

2

Saya lebih suka solusi John T, tetapi jika Anda ingin menggunakan semua kode golf, pernyataan Anda secara logis direduksi menjadi ini:

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

Tidakkah Anda harus memeriksa wParam terhadap VK_F11 dan VK_F12?
drby


0

Jelas Anda membutuhkan solusi fleksibel yang dapat mendukung tipe yang menyamar sebagai boolean. Hal berikut memungkinkan untuk itu:

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

Anda kemudian dapat mengkhususkan ini untuk berbagai jenis yang mungkin berpura-pura menjadi boolean. Sebagai contoh:

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

Contoh penggunaan konstruksi ini:

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

Tidak, saya tidak serius.


0

Untuk bilangan bulat dengan nilai 0 dan 1 Anda dapat mencoba:

value = abs(value - 1);

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

Hanya karena saya suka mempertanyakan kode. Saya mengusulkan agar Anda juga dapat menggunakan terner dengan melakukan sesuatu seperti ini:

Contoh:

bool flipValue = false;
bool bShouldFlip = true;
flipValue = bShouldFlip ? !flipValue : flipValue;
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.