2012-05-30 15 views
22

Więc jestem ciekawy, dlaczego tak się dzieje.C++ Ocena Boolean

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

oczekiwanego zachowania: 0 - zakończenie programu 1 - Polecenia ponownie Każdy niezerowy całkowitą inną niż 1 - Polecenia ponownie

Niektóre procesy: 0 - Jak oczekiwano, 1 - Zgodnie z oczekiwaniami, Każdy niezerowy całkowitą inną niż 1 - nieskończonej pętli

Z 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. 

Dlaczego program przechodzi w nieskończoną pętlę?

+8

+1 za dobrze zadane pytanie.Boolean jest czerwonym śledziem; prawdziwy problem związany jest ze sposobem działania strumienia wejściowego. Wypróbuj to samo z int, a następnie wpisz literę i zobacz, co się dzieje ;-) – Cameron

+0

Może się mylę, ale kiedy weźmiesz wejściową linię poleceń ... nie stanie się to ciągiem znaków, więc w rzeczywistości konwersja między łańcuchem a boolowem? Co może zepsuć ... –

+0

Cameron ma dobry punkt: postać może zostać przekonwertowana na liczbę całkowitą. Na przykład "A" == 65', ale to samo się dzieje. – chris

Odpowiedz

23

W efekcie przeciążenia operator>> używany do czytania bool tylko pozwala wartość 0 lub 1 jako ważny wkład. Przeciążenia operatora odsuwa do matrycy num_get klasy, który stanowi kolejny numer ze strumienia wejściowego i zachowuje się w sposób następujący (C++ 11 §22.4.2.1/6):

  • Jeżeli wartość być przechowywany jest 0 następnie przechowywany jest false.

  • Jeśli wartość wynosi 1, wówczas przechowywana jest true.

  • W przeciwnym razie przechowywany jest true, a ios_base::failbit jest przypisany do err.

(err tutaj jest stan błędu strumienia, z którego czytasz;. cin w tym przypadku pamiętać, że tam jest określenie zachowania dodatkowy język, gdy używany jest boolalpha manipulator, który umożliwia wartości logicznych do brzmieniu i ekstrahowano przy użyciu ich nazw, true i false;. i pominięto także inne szczegóły dotyczące zwięzłość)

po wprowadzeniu wartości innej niż zero lub jeden, państwo nie zostanie ustawiony na strumień, co powoduje dalsze ekstrakcje nie zdać. answer jest ustawiony na true i pozostaje na zawsze true powodując nieskończoną pętlę.

Należy przetestować stan strumienia po każdym wyodrębnieniu, aby sprawdzić, czy wyodrębnianie zakończyło się pomyślnie i czy strumień jest nadal w dobrym stanie. Na przykład możesz przepisać swoją pętlę jako:

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

+1: O wiele lepsza odpowiedź niż zaakceptowana, ponieważ wyjaśnia, że ​​standard nakazuje takie zachowanie. –

+0

Uzgodnione :) Zmieniono odpowiedź, aby odzwierciedlić dając lepsze zrozumienie. Zdecydowanie przykład, dlaczego walidacja wejściowa jest zawsze ważna :) –

15

Ponieważ operator>> nie powiedzie się, jeśli wejście nie ma wartości 0 lub 1, a gdy się nie powiedzie, nie zużywa sygnału wejściowego. Zatem pętla polega na wielokrotnym odczytywaniu cyfry, a następnie jej odczycie.

Spróbuj zmienić kod tak, żeby go zobaczyć:

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

Chociaż zazwyczaj chcesz napisać 'if (! (Cin >> answer))' zamiast 'cin >> answer; if (cin.fail()) ' –

+0

Po prostu wypróbowałem to i program w pewnym sensie" zawiesił się ", jeśli tylko coś wpiszesz i naciśniesz return. Jeśli jednak wpiszesz go ponownie, przejdzie on do oceny danych wejściowych. Czemu? –

+3

Rewizja za propagowanie anty-wzorca 'if (cin.fail()). Przetestuj wynik operacji (jak sugeruje @SteveJessop), a nie stan strumienia. –