Cách dễ nhất để lật một giá trị boolean?


123

Tôi chỉ muốn lật một boolean dựa trên những gì nó đã có. Nếu nó đúng - làm cho nó sai. Nếu nó sai - làm cho nó đúng.

Đây là đoạn trích mã của tôi:

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

Câu trả lời:


339

Bạn có thể lật một giá trị như vậy:

myVal = !myVal;

vì vậy mã của bạn sẽ rút ngắn xuống:

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

    case VK_F12:
    otherVal = !otherVal;
    break;

    default:
    break;
}

7
Đây không chỉ là cách dễ nhất mà còn là cách sạch nhất.
sharptooth

hai trường hợp có thể được hợp nhất khi chúng làm điều tương tự.
David Allan Finch

1
Là mặc định: phá vỡ; vô cùng cần thiết? Công tắc không kết thúc giống nhau mà không có nó?
Chris Lutz

12
Mặc định: nghỉ; là không cần thiết
Rob K

4
Nếu bạn đang bật một cái gì đó dài dòng như object1-> system1.system2.system3.parameter1 thì có thể có macro TOGGLE (a). Điều này ngăn ngừa một số sai lầm và làm cho tất cả dễ đọc hơn trên màn hình hẹp.
OJW

77

Rõ ràng bạn cần một mô hình nhà máy!

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
Chúng tôi có lẽ có thể thêm vào mô hình singleton cho nhà máy quá.
vẽ

@Orm Nguyên nhân bạn là ORM ? :)
mlvljr

3
Lưu ý đề xuất tinh tế để chuyển sang Java!
Ốc cơ khí

Chà ... tôi nghĩ rằng chúng ta cần một bản phát hành chính khác của C ++ cho bản này, có thể là C ++ / 51
0x6900

Này các cậu! Tôi nghĩ rằng cách tiếp cận của bạn không phải là reentrant. Bạn cần ít nhất nguyên tử_bool, tốt hơn là một mutex hoặc hàng đợi sự kiện. Hơn nữa, chúng ta cần một mô hình quan sát viên để theo dõi trạng thái của val.
Marco Freudenberger

38

Nếu bạn biết các giá trị là 0 hoặc 1, bạn có thể làm flipval ^= 1.


1
Tại sao sử dụng một toán tử bitwise cho một hoạt động hợp lý? Mùi của obfuscation không cần thiết với tôi.
Đánh dấu Pim

5
@Mark: Xin lỗi. Đoán tôi là người cổ điển. Nhưng nó có ích nếu biểu thức giá trị L của bạn thực sự dài, vì vậy bạn không phải lặp lại. Ngoài ra, bạn có thể nói flipval ^ = TRUE. Điều đó có tốt hơn không?
Mike Dunlavey

6
@Alnitak: Bạn đúng trong một số trường hợp. Tôi đã thấy một số người đóng gói các bit lại với nhau để "tiết kiệm không gian" và hành động như thể các hướng dẫn để truy cập chúng không chiếm bất kỳ dung lượng nào.
Mike Dunlavey

2
@Albert: ^là nhà điều hành độc quyền . 0^11, và 1^10. Nó giống như thêm nếu bạn bỏ qua bit carry. Hoặc bạn có thể nghĩ về nó như - nếu một trong hai bit là 1, kết quả là nghịch đảo của bit kia. Hoặc bạn có thể nghĩ về nó khi đặt câu hỏi: Hai bit này có khác nhau không?
Mike Dunlavey

1
@MikeDunlavey nếu bạn đang sử dụng thiết bị có 4M Flash cho không gian mã và 3K SRAM cho không gian dữ liệu thì đó là cách hành động hợp lý!
MM

33

Giải pháp dễ nhất mà tôi tìm thấy:

x ^= true;

11
x = !x;không chỉ ngắn hơn, mà còn dễ đọc hơn.
Rodrigo

13
Lưu ý rằng ví dụ longVariableName ^= true;rõ ràng là ngắn hơn longVariableName = !longVariableName;Và mọi lập trình viên nên biết XOR.
xamid

a ^= bcó nghĩa là a = a ^ b, nơi ^có nghĩa là XOR. Ký hiệu a °= bcho a = a ° bbất kỳ toán tử nào °là rất phổ biến trong cú pháp C / C ++ / C #.
xamid

2
Giai thoại, nhưng gần đây tôi đã bắt gặp dòng gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value = !gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value;Tất nhiên, điều rõ ràng nhất cần làm là mở rộng nó thành nhiều dòng và sử dụng các biến tạm thời để lưu trữ các đối tượng, nhưng gRackWidget->modules->first().lights[PATTERN1_LIGHT + i].value ^= 1dễ đọc hơn, ít lỗi hơn và ít ký tự hơn mã gốc .
Vortico

1
Ngoài ra, ít trùng lặp hơn có nghĩa là ít có cơ hội quên cập nhật BÓNG của phương trình trong các thay đổi phát triển nhanh / ngày dài / đêm mã hóa.
Chuyến đi Katastic

11

Chỉ để biết thông tin - nếu thay vì số nguyên, trường bắt buộc của bạn là một bit trong loại lớn hơn, hãy sử dụng toán tử 'xor' thay thế:

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

Đây dường như là một thứ miễn phí cho tất cả ... Heh. Đây là một biến thể khác, mà tôi đoán là trong danh mục "thông minh" hơn là thứ tôi khuyên dùng cho mã sản xuất:

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

Tôi đoán đó là ưu điểm của nó là:

  • Rất ngắn gọn
  • Không yêu cầu phân nhánh

Và một nhược điểm rõ ràng là

  • Rất ngắn gọn

Điều này gần với giải pháp của @ korona bằng cách sử dụng ?: Nhưng đã tiến thêm một bước (nhỏ).


2
Theo thứ tự các thao tác, tôi nghĩ bạn có thể bỏ qua dấu ngoặc đơn để thậm chí còn ngắn gọn hơn. : O
vẽ

8

Chỉ vì cách bóng kỳ lạ yêu thích của tôi để chuyển đổi một bool không được liệt kê ...

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

làm việc quá :)

(vâng, x = !x;rõ ràng và dễ đọc hơn)


6

Giải pháp codegolf'ish sẽ giống như:

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

2

Tôi thích giải pháp của John T, nhưng nếu bạn muốn chơi tất cả các môn đánh gôn, tuyên bố của bạn sẽ giảm một cách hợp lý điều này:

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

Bạn không phải kiểm tra wParam với VK_F11 và VK_F12?
drby


0

Rõ ràng bạn cần một giải pháp linh hoạt có thể hỗ trợ các kiểu giả mạo như boolean. Sau đây cho phép:

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

Sau đó, bạn có thể chuyên môn hóa này cho các loại khác nhau có thể giả vờ là boolean. Ví dụ:

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

Một ví dụ về việc sử dụng cấu trúc này:

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

Không, tôi không nghiêm túc.


0

Đối với các số nguyên có giá trị 0 và 1, bạn có thể thử:

value = abs(value - 1);

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

Chỉ vì tôi thích đặt câu hỏi về mã. Tôi đề nghị rằng bạn cũng có thể sử dụng chim nhạn bằng cách làm một cái gì đó như thế này:

Thí dụ:

bool flipValue = false;
bool bShouldFlip = true;
flipValue = bShouldFlip ? !flipValue : flipValue;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.