2012-11-08 7 views
7

Powiedz, że mam program, który przyjmuje liczby całkowite. Jak zatrzymać program przed rozpadem, jeśli użytkownik wprowadzi numer spoza zakresu lub literę lub coś takiego?Jak zdezynfekować Cin?

+4

http://www.parashift.com/c++-faq/istream-and-ignore.html – chris

Odpowiedz

2

klasa bazowy cin „s jest std::basic_istream. Strumień wejściowy wskazuje możliwy do naprawienia błąd w przypadku, gdy nie może wyodrębnić żądanych danych ze strumienia. Aby sprawdzić ten bit błędu, należy użyć metody std::basic_istream::fail() - zwraca ona true, jeśli wystąpiła awaria lub false, jeśli wszystko jest w porządku. Należy pamiętać, że w przypadku wystąpienia błędu dane pozostają w strumieniu i oczywiście bit (y) błędu należy również wyczyścić, używając std::basic_istream::clear(). Ponadto programista musi zignorować niepoprawne dane lub w przeciwnym razie próba odczytania czegoś innego zakończy się niepowodzeniem. W tym celu można zastosować metodę std::basic_istream::ignore(). Jeśli chodzi o prawidłowy zakres wartości, należy go sprawdzić ręcznie. Okay, dość teorii, oto prosty przykład:

#include <limits> 
#include <iostream> 

int main() 
{ 
    int n = 0; 

    for (;;) { 
     std::cout << "Please enter a number from 1 to 10: " << std::flush; 
     std::cin >> n; 

     if (std::cin.fail()) { 
      std::cerr << "Sorry, I cannot read that. Please try again." << std::endl; 
      std::cin.clear(); 
      std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
      continue; 
     } 

     if (n < 1 || n > 10) { 
      std::cerr << "Sorry, the number is out of range." << std::endl; 
      continue; 
     } 

     std::cout << "You have entered " << n << ". Thank you!" << std::endl; 
     break; 
    } 
} 

Mam nadzieję, że to pomaga. Powodzenia!

2

coś takiego powinien zrobić trzeba wyczyścić bufor po sprawdzeniu aswell jeśli dobrze pamiętam

if (cin.fail()) 
    { 
     cout<<"need to put a number"<<endl; 
     cin.clear(); 
     cin.ignore(); 
    } 
0

Jeśli nie chcesz dodawać bibliotek do swojego kodu, możesz również użyć instrukcji do..while(). w swoim życiu, podczas gdy poprosisz o dane wejściowe użytkownika, a następnie otrzymasz je do zmiennej, a następnie w części while będziesz mógł sprawdzić, czy są to dane, których się spodziewasz, jeśli nie będziesz dalej pytać o dane.

prostu innej opcji .... mimo, że odpowiedź już wspomniano powinien pracować więcej niż odpowiednio

4

Wolę czyta wejście jako ciągi i następnie odkażania im boost::lexical_cast<>:

#include <boost/lexical_cast.hpp> 
#include <iostream> 
#include <string> 

int main() { 
    std::string s; 
    while(std::cin >> s) { 
    try { 
     int i = boost::lexical_cast<int>(s); 
     std::cout << "You entered: " << i << "\n"; 
    } catch(const std::bad_cast&) { 
     std::cout << "Ignoring non-number: " << s << "\n"; 
    } 
    } 
} 

Postscriptum: Jeśli masz uczulenie na Boost, możesz użyć tej implementacji leksykalnej:

template <class T, class U> 
T lexical_cast(const U& u) { 
    T t; 
    std::stringstream s; 
    s << u; 
    s >> t; 
    if(!s) 
    throw std::bad_cast(); 
    if(s.get() != std::stringstream::traits_type::eof()) 
    throw std::bad_cast(); 
    return t; 
} 
+0

Klauzula catch-all bez ponownego rzutu jest nie-nie. –

+0

Czy możesz to wyjaśnić lub podać cytat? –

+0

@ VladLazarenko: Naprawiono. –

0

Można użyć następującego kodu do najprostszego i szybkiego sprawdzenia ważnego wkładu w int:

#include "stdafx.h" 

#include <iostream> 
using namespace std; 

int main() 
{ 

    int intb; 
    while(!(cin>>intb)){ 
     cin.clear(); 
     cin.ignore (1000, '\n'); 
     cout<<"Invalid input enter again: "<<endl; 

    } 
    cout<<"The value of integer entered is "<<b<<endl; 

     return 0; 
} 

pętli while utrzymuje się na iterację aż dostaje prawo wejścia. cin.clear() zmienia stan kontroli błędów. cin.ignore() usuwa usuwanie strumienia wejściowego, dzięki czemu można ponownie pobierać nowe dane wejściowe. Jeśli nie zrobisz tego, pętla będzie w nieskończonym stanie.

Powiązane problemy