2012-10-04 28 views
6

Powiel możliwe:
how do I validate user input as a double in C++?C++, jak zweryfikować to wejście danych jest prawidłowy typ danych

Jestem nowym do C++ i mam funkcji, w których jestem chcąc, aby użytkownik wprowadził wartość double. W jaki sposób chciałbym się upewnić, że wartość wejściowa była właściwego typu danych? W jaki sposób można rozwiązać błąd? W tej chwili jest to wszystko, co mam:

if(cin >> radius){}else{} 

I używając `try {} catch() {}, ale nie sądzę, że właściwe rozwiązanie tego problemu. Każda pomoc będzie doceniona.

+4

Działa to całkiem dobrze: http://www.parashift.com/c++-faq/istream-and-ignore.html – chris

+1

odczytywać jako ciąg i analizować za pomocą wyrażenia regularnego. – rplusg

Odpowiedz

13

Jeśli ostream& operator>>(ostream& , T&) nie ekstrakcję sformatowanych danych (takich jak liczba całkowita, podwójne, pływak, ...), stream.fail() będzie prawdziwe, a tym samym !stream oceni true też.

Więc można użyć

cin >> radius; 
if(!cin){ 
    cout << "Bad value!"; 
    cin.clear(); 
    cin.ignore(numeric_limits<streamsize>::max(), '\n'); 
    cin >> radius; 
} 

lub po prostu

while(!(cin >> radius)){ 
    cout << "Bad value!"; 
    cin.clear(); 
    cin.ignore(numeric_limits<streamsize>::max(), '\n'); 
} 

Ważne jest ignore reszta linii, ponieważ operator>> nie będzie wyodrębnić żadnych danych ze strumienia już, jak to jest w niewłaściwym formacie. Jeśli więc usuniesz swoją pętlę, to nigdy nie skończysz, ponieważ wejście nie zostanie usunięte ze standardowego wejścia.

Zobacz także:

+1

'sream.good()' może być fałszywe, nawet jeśli dane wejściowe są poprawne. A gdy używasz strumienia w kontekście logicznym, false to 'stream.fail()', a true to '! Stream.fail()'; 'stream.good()' nigdy nie wchodzi w to. Wszelkie odniesienia do "istream :: good" w odniesieniu do problemu z plakatem są błędne. –

+3

Twoje stwierdzenie, że 'operator >>' nie wyodrębni żadnych danych ze strumienia, jeśli nie jest we właściwym formacie, również jest błędne; może wyodrębnić część danych. (Pomyśl o wejściu podobnym do "1.2e + x" '.Strumienie gwarantują tylko jedno spojrzenie z wyprzedzeniem, a błąd nie może zostać wykryty, dopóki nie zobaczymy '' x''. Wszystkie poprzednie postacie zostaną wyodrębnione.) –

+0

@JamesKanze: Starałem się zająć troskami w obu twoich komentarzach, jednak wciąż wydaje się trochę niezgrabny. Zajrzę później, jeśli znajdziesz inny błąd, możesz edytować i zostawić komentarz. Zawsze dobrze jest nauczyć się czegoś nowego :). – Zeta

3

Musisz przeczytać całą linię, używając std::getline i std::string. To jest sposób, aby w pełni zweryfikować, że cała linia jest odpowiedniego typu danych:

std::string line; 
while(std::getline(std::cin, line)) 
{ 
    std::stringstream ss(line); 
    if ((ss >> radius) && ss.eof()) 
    { 
     // Okay break out of loop 
     break; 
    } 
    else 
    { 
     // Error! 
     std::cout << "Invalid input" << std::endl; 
    } 
} 
0

Ten przykład jest oczywista, jednak z takim podejściem nie można odróżnić int i double.

int main() 
{ 
    double number = 0; 

    if (!(std::cin >> number)) 
    { 
    std::cout << "That's not a number; "; 
    } 
    else 
    { 
    std::cout << "That's a number; "; 
    } 
} 
+2

Uhm A co jeśli wejdą, powiedzmy, 0? Czy to nie będzie działać z częścią ints .. – StarWind0