2012-05-30 36 views
22

Vì vậy, tôi tò mò là tại sao điều này xảy ra.C++ Đánh giá Boolean

int main() 
{ 
    bool answer = true; 
    while(answer) 
    { 
     cout << "\nInput?\n"; 
     cin >> answer; 
    } 
return 0; 
} 

hành vi dự kiến: 0 - Thoát chương trình, 1 - Gợi ý một lần nữa, Bất kỳ khác không số nguyên khác hơn là 1 - Gợi ý một lần nữa

hành vi thực tế: 0 - Đúng như dự đoán, 1 - Đúng như dự đoán, Bất kỳ khác không số nguyên khác hơn là 1 - Infinite loop

Từ http://www.learncpp.com/cpp-tutorial/26-boolean-values/

One additional note: when converting integers to booleans, 
the integer zero resolves to boolean false, 
whereas non-zero integers all resolve to true. 

Tại sao chương trình đi vào vòng lặp vô hạn?

+8

+1 cho câu hỏi đặt ra.Boolean là một cá trích đỏ; vấn đề thực sự phải làm với cách hoạt động của luồng đầu vào. Hãy thử những điều tương tự với một int, và sau đó nhập một lá thư và xem những gì sẽ xảy ra ;-) – Cameron

+0

Có lẽ tôi sai nhưng khi bạn lấy dòng lệnh đầu vào hình thức ... không phải là trở thành một chuỗi và do đó bạn đang thực sự chuyển đổi giữa chuỗi và boolean? Điều này có thể khiến mọi việc trở nên khó khăn. –

+0

Cameron làm cho một điểm tốt: một nhân vật có thể được chuyển đổi thành một số nguyên. Ví dụ, '' A '== 65', nhưng điều tương tự cũng xảy ra. – chris

Trả lời

23

Trên thực tế, tình trạng quá tải operator>> dùng để đọc một bool chỉ cho phép một giá trị của 0 hoặc 1 đầu vào là hợp lệ. Sự quá tải toán tử hoãn đến mẫu num_get lớp, mà đọc số kế tiếp từ dòng đầu vào và sau đó hoạt động như sau (C++ 11 §22.4.2.1/6):

  • Nếu giá trị để được lưu trữ là 0 thì false được lưu trữ.

  • Nếu giá trị là 1 thì true được lưu trữ.

  • Nếu không true được lưu trữ và ios_base::failbit được gán cho err.

(err đây là trạng thái lỗi của con suối từ đó bạn đang đọc;. cin trong trường hợp này Lưu ý rằng có ngôn ngữ bổ sung quy định cụ thể hành vi khi thao túng boolalpha được sử dụng, cho phép các phép toán luận để được chèn vào và trích xuất bằng tên của chúng, truefalse; Tôi đã bỏ qua các chi tiết khác này ngắn gọn.)

Khi bạn nhập giá trị khác 0 hoặc 0, thì trạng thái lỗi sẽ được đặt trên luồng. thất bại. answer được đặt thành true và giữ nguyên mãi mãi là true, gây ra vòng lặp vô hạn.

Bạn phải kiểm tra trạng thái của luồng sau mỗi lần trích xuất để xem liệu quá trình trích xuất có thành công hay không và liệu luồng có còn ở trạng thái tốt hay không. Ví dụ: bạn có thể viết lại vòng lặp của mình dưới dạng:

bool answer = true; 
while (std::cin && answer) 
{ 
    std::cout << "\nInput?\n"; 
    std::cin >> answer; 
} 
+0

+1: Câu trả lời tốt hơn nhiều so với câu trả lời được chấp nhận bởi vì nó giải thích rằng tiêu chuẩn ủy nhiệm hành vi này. –

+0

Đồng ý :) Đã thay đổi câu trả lời để phản ánh sự hiểu biết tốt hơn. Chắc chắn một ví dụ về lý do tại sao xác thực đầu vào luôn quan trọng :) –

15

operator>> không thành công nếu đầu vào không phải là 0 hoặc 1 và khi không thành công, nó không tiêu thụ đầu vào. Vì vậy, vòng lặp bao gồm đọc chữ số và sau đó bỏ đọc nó, nhiều lần.

Hãy thử thay đổi mã như thế này để xem nó:

if (cin >> answer) { 
    cout << answer << endl; 
} else { 
    cerr << "oops" << endl; 
    break; 
} 
+4

Mặc dù bạn thường muốn viết 'if (! (Cin >> answer))' thay vì 'cin >> answer; if (cin.fail()) ' –

+0

Chỉ cần thử điều này và loại chương trình" treo "nếu bạn chỉ cần gõ vào một cái gì đó và nhấn trở lại. Tuy nhiên, nếu bạn gõ lại, nó sẽ tiếp tục đánh giá đầu vào. Tại sao? –

+3

Bị bỏ qua để tuyên truyền mẫu 'if (cin.fail())'. Kiểm tra kết quả của phép toán (như @SteveJessop gợi ý) chứ không phải trạng thái luồng. –

Các vấn đề liên quan