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.