2012-01-10 59 views
40

Câu hỏi chủ yếu là vui chơi/tò mò: cách viết vòng lặp for trong C++ để lặp qua hai giá trị bool (ví dụ: truefalse) , chỉ sử dụng các hoạt động với bool (nghĩa là không có chuyển đổi cho các loại khác)?Cách viết vòng lặp `for` qua giá trị bool (sai và đúng)

Nền là tôi muốn kiểm tra có bao nhiêu giải pháp tồn tại cho một phương trình như (A && B) || (!B && !C && !D) == true, và bắt đầu viết một cái gì đó giống như for (bool A=false; ??? ; ++A) for (bool B=false; ...) vv nhưng ngay lập tức đã bị mắc kẹt bởi ??? - ví dụ: những gì sẽ là điều kiện để tiếp tục vòng lặp? Tất nhiên tôi viết lại nó để sử dụng int, và tôi cũng biết rằng một vòng lặp do ... while sẽ làm việc, nhưng tôi đã tò mò nếu nó bao giờ có thể viết như một vòng lặp for? Và kể từ khi SO dường như không có một câu trả lời, tôi quyết định hỏi :)


Cập nhật: lưu ý rằng một "rõ ràng" biến thể for(bool A=false; !A; A=true) đề xuất trong ít nhất hai câu trả lời đã bị loại bỏ sẽ chỉ chạy một lần lặp, vì đối với điều kiện thứ hai, điều kiện !A trở thành false và vòng lặp kết thúc.

Sau khi cân nhắc, tôi tin rằng không thể làm điều đó trong C++ 03 mà không có biến thứ hai hoặc cấu trúc dựa trên con trỏ như được gợi ý bởi Dietmar Kühl. Các điều kiện cần được kiểm tra ba lần trong một thực hiện mong muốn, do đó, hai giá trị của một bool chỉ đơn giản là không đủ. Và vòng lặp do-while hoạt động vì vòng lặp đầu tiên được thực hiện vô điều kiện, điều kiện chỉ được kiểm tra hai lần và do đó giá trị bool có thể được sử dụng để chọn giữa tiếp tục và thoát.

+2

Thật là tuyệt vời khi các câu trả lời sai bị xóa đi! –

+1

Có, bạn không ghét nó khi họ làm điều này? Tôi thấy đó là một câu hỏi hay. Tôi upvoted. –

+0

Bởi vì trang web này không phải là niềm vui/sự tò mò. Câu hỏi thực sự! PS Không, không phải tôi, tôi cũng tò mò. –

Trả lời

48

Trong C++ 11: for (bool b : { false, true }) { /* ... */ }


Dưới đây là một phiên bản C++ 03: (. Sử dụng một trong hai a hoặc b)

for (bool a = true, b = false; b != a; a = a && b, b = !b) { /*...*/ } 

+1

Đó là một phiên bản thú vị với danh sách khởi tạo. – Xeo

1

này một công trình , quá:

for (bool a = false, b = false; a == b; b = !b, a = a || b) { } 

(loại dung dịch ngược hơn @ KerrekSB của)

6

Khi giới hạn trong C++ 2003 bạn có thể sử dụng một cách tiếp cận tương đương với phương pháp C++ 2011;

{ 
    bool const bools[] = { false, true }; 
    for (bool const* it(bools); it != std::end(bools); ++it) { 
     bool a(*it); 
     use(a); 
    } 
} 

Có thể đóng gói trong macro. Bạn cũng có thể sử dụng

for (bool a: { false, true }) { 
    use(a); 
} 
+0

Tôi nghĩ rằng bạn có thể có thể gói mảng đó vào phần khai báo của vòng lặp for. Không chắc chắn mặc dù. – Xeo

+0

Phép thuật 2 của bạn mâu thuẫn với toàn bộ ý tưởng. – Wolf

+1

@Wolf: phản hồi được viết vào năm 2012. Tôi đoán, tôi không cho rằng C++ 11 thường có sẵn (mặc dù tôi đã phát hiện ra chức năng cần thiết để thực hiện 'std :: end()' -1998. –

2

Một hơn cho C++ 03:

for(bool a = false, b = true; b; a = !a, b = a) 

Sử dụng b.

4
for (int a = 0; a <= 1; a++) 
    doStuff(a ? true : false); 

Và quên giới hạn "không chuyển đổi sang các loại khác" :) Vào cuối ngày, sự rõ ràng quan trọng hơn giới hạn nhân tạo. Năm năm xuống dòng bạn sẽ được đọc mã của riêng bạn và tự hỏi "những gì tôi đang nghĩ, đây là một số loại của một cuộc thi obfuscation?"

+0

Nếu bạn sử dụng' char'/'uint8_t' thay vì' int', sẽ có cơ hội tốt để chúng biên dịch vào cùng một kiểu dữ liệu cơ bản và cung cấp cho bạn tính năng đúc không tốn phí. –

+0

@ SlippD.Thompson Nó phụ thuộc vào 'doStuff' cho dù' int' có hiệu quả hay không. – Wolf

4
a = true; 
do { 
    use(a); 
    a = !a; 
} while (!a); 

OK, vì vậy nó không phải là một cho vòng lặp, nhưng tôi sẽ tranh luận đó là dễ đọc hơn so bất kỳ cho các đề xuất loop (khác so với phương pháp C++ 11, tất nhiên.)

+0

Để làm cho 'tiếp tục' hoạt động bên trong vòng lặp như mong đợi:' a = false; làm {...} trong khi (a =! a); '. Giá trị ban đầu trong một biến/hằng số: 'a = init; do {...} while (init! = (a =! a)); ' – adf88

2

Câu trả lời này giải quyết "không thể" C++ 03, giải pháp duy nhất biến duy nhất

Trước tiên, hãy xác nhận rằng không có biểu thức số học xác định chỉ dựa trên một biến đầu vào có thể đúng cho cả hai đầu vào true,false. đối với giá trị thứ ba phải là một trong số true hoặc false .

Tuy nhiên, chúng tôi có thể "gian lận". Mặc dù, tôi sẽ yêu cầu bạn chứng minh tôi thực sự lừa dối.

#include <iostream> 

using namespace std; 

int main() { 
    for (bool b = false; *((char*)&b) != 2; *((char*)&b) += 1) { 
     cout << "bool " << b << endl; 
    } 
} 

Điều này chắc chắn dường như như hành vi không xác định. C++ 03 là một bit unclear about it. Tuy nhiên, sizeof phải luôn có ít nhất 1 (với ngoại lệ không chuẩn cho mảng var-len có chiều dài 0). Hơn nữa, vì chúng tôi đảm bảo mỗi char có ít nhất 8 bit, chúng tôi có thể sử dụng thẻ thứ hai cho bộ đếm của chúng tôi. Thật vậy, để làm được điều này, chúng ta cần phải xác định váy (không thể không từ bỏ bảo đảm chúng ta lặp lại trên false, true chính xác một lần) hoặc hệ thống kiểu ràng buộc của chúng ta.

0

Tôi biết bạn đã yêu cầu giải pháp mà không cần chuyển đổi sang loại khác, nhưng tôi cho rằng bạn có nghĩa là "không chuyển đổi thành loại khác không được phân bổ". Đây là một câu trả lời cung cấp một đối tượng thay thế bool trong trường hợp cụ thể này.

struct IterableBool 
{ 
    bool b; 
    bool out_of_scope; 
    IterableBool() : b(false), out_of_scope(false) {} 
    IterableBool(bool b_) : b(b_), out_of_scope(false) {} 
    IterableBool(IterableBool ib) : b(ib.b), out_of_scope(ib.out_of_scope) {} 
    operator bool() { return this->b; } 
    bool in_scope() const { return !this->out_of_scope; } 
    IterableBool& operator ++() 
    {      
    this->out_of_scope = this->b; 
    this->b = true; 
    return *this; 
    } 
    IterableBool operator ++ (int) 
    { 
    IterableBool copy = *this; 
    ++(*this); 
    return copy; 
    } 
    IterableBool& operator --() 
    { 
    this->out_of_scope = !this->b; 
    this->b = false; 
    return *this; 
    } 
    IterableBool operator -- (int) 
    { 
    IterableBool copy = *this; 
    --(*this); 
    return copy; 
    } 
}; 

// Usage : 
for(IterableBool ib = false; ib.in_scope(); ++ib) 
    do_stuff((bool)ib); 
Các vấn đề liên quan