2013-04-26 15 views
8

Znalazłem ten link pod numerem http://www.parashift.com/c++-faq-lite/istream-and-ignore.htmlC++ Przykład: Nie jesteś w stanie zrozumieć, co się robi?

, który pokazuje "Jak mogę uzyskać std :: cin, aby pominąć nieprawidłowe znaki wejściowe?"

Use std::cin.clear() and std::cin.ignore(). 

#include <iostream> 
#include <limits> 

int main() 
{ 
    int age = 0; 

    while ((std::cout << "How old are you? ") 
     && !(std::cin >> age)) { 
    std::cout << "That's not a number; "; 
    std::cin.clear(); 
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
    } 

    std::cout << "You are " << age << " years old\n"; 
    ... 
} 
Of course you can also print the error message when the input is out of range. For example, if you wanted the age to be between 1 and 200, you could change the while loop to: 
    ... 
    while ((std::cout << "How old are you? ") 
     && (!(std::cin >> age) || age < 1 || age > 200)) { 
    std::cout << "That's not a number between 1 and 200; "; 
    std::cin.clear(); 
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
    } 
    ... 
Here's a sample run: 
How old are you? foo 
That's not a number between 1 and 200; How old are you? bar 
That's not a number between 1 and 200; How old are you? -3 
That's not a number between 1 and 200; How old are you? 0 
That's not a number between 1 and 200; How old are you? 201 
That's not a number between 1 and 200; How old are you? 2 
You are 2 years old 

Nie jestem w stanie uzyskać tego, jak to robi> Czy ktoś może wyjaśnić?

mam wątpliwości z:

while ((std::cout << "How old are you? ") 
      && !(std::cin >> age)) 

Jak to jest sprawdzanie poprawny wpis? Chcę zapytać o wyrażenia "std :: cout < <" Ile masz lat? "I"! (Std :: cin >> age) ", zwróć true lub false, które są ANDed?

kolejna rzecz, która jest mylące jest użycie,

std::cin.clear(); 
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 

Jakie są tam cel? Szukano w Google na temat tych funkcji, ale nadal nie jestem jasne. Szczególnie std::numeric_limits<std::streamsize>::max()

może ktoś pomóc? Dzięki

+0

cin.clear() i cin.ignore() służy do zapobiegania CIN za pomijanie, (jeśli nie źle). Po raz pierwszy myślę, że to niewłaściwe pytanie. – cakil

Odpowiedz

10

Operatory wstawiania i usuwania << i >> na strumieniach zwrócą odniesienie do samego strumienia. Dlatego można strunowe razem wstawki tak:

std::cout << "Hello, " << "World!"; 

Pierwszy std::cout << "Hello, " zwraca odwołanie do std::cout i potem trzeba równowartość std::cout << "World!".

Strumienia można również przekonwertować na bool. To zasadniczo sprawdza, czy stan strumienia jest nadal w porządku. Nic nie zawiodło. Na przykład, można to zrobić:

if (std::cin) // ... 

byłoby to sprawdzić, czy strumień std::cin jest nadal w dobrym stanie.

Teraz spójrzmy na kod, który poprosił o:

while ((std::cout << "How old are you? ") 
     && !(std::cin >> age)) 

Wprowadzenie do std::cout nie spowoduje awarię. Jedyny powód, dla którego jest tu zawarty, jest taki, że występuje za każdym razem przed wprowadzeniem do age. Alternatywą byłoby umieszczenie go raz przed while i raz na końcu ciała while.

Po zakończeniu wstawiania do std::cout zostaną ocenione wartości !(std::cin >> age). Najpierw poprosimy użytkownika o dostarczenie age. Następnie dwie rzeczy mogą się zdarzyć:

  1. Jeśli to się nie powiedzie w jakiś sposób (być może użytkownik wprowadzi znaki zamiast liczby całkowitej), wówczas nie zostanie ustawiony bit. Oznacza to, że wynik std::cin >> age zostanie przekonwertowany na bool, który będzie false. ! zmieni go na true. Ponieważ zarówno pierwszy, jak i drugi warunek były prawdziwe, ciało pętli while wykona polecenie, informując użytkownika, że ​​wprowadzono niepoprawną wartość, a pętla zostanie ponownie powtórzona.

  2. jeśli wejście powiedzie, wynikiem std::cin >> age będzie true i ! włączy go do false. Oznacza to, że korpus pętli while nie zostanie wykonany i nie powie użytkownikowi, że wprowadził niepoprawną wartość.

Teraz przyjrzyjmy:

std::cin.clear(); 
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 

Dzieje się tak tylko w przypadku 1, gdy wejście nie powiodło się. Jeśli strumień przejdzie w stan awarii, nie zaakceptuje żadnych kolejnych wstawień lub ekstrakcji, dopóki stan nie zostanie usunięty. To właśnie robi clear(). Następnie wywołanie ignore mówi, aby wyodrębnić w strumieniu wszystkie znaki do następnego \n włącznie i odrzucić je. Spowoduje to usunięcie nieprawidłowych danych wejściowych ze strumienia.

+0

"Następnie wywołanie zignorowania mówi, aby wyodrębnić wszystkie znaki do następnego \ n w strumieniu i je odrzucić, co pozbywa się nieprawidłowego wejścia ze strumienia." - oznacza znak nowej linii '\ n' jest nadal w strumieniu, nie będzie "\ n" jako wejście w następnej iteracji "Ile masz lat?" –

+0

@GauravK Przepraszamy, powinno być "do i włącznie z następnym' \ n' ". –

+0

Nie, po prostu chcę wiedzieć, czy ignore() odrzuca także kreskę, ponieważ to, co przeczytałem, jeśli Delim jest EOF, nie jest odrzucane, jeśli jest inne niż "EOF" - czy jest również wyodrębniane i odrzucane? –

0

Jak age jest liczbą całkowitą

(std::cin >> age) 

próbuje analizować dane wejściowe, aby uzyskać poprawną liczbą całkowitą, jeśli może to return true, w przeciwnym razie zwraca false.

wiedzieć o cin.ignore, to będzie ..

ekstrakty i usuwa znaki ze strumienia wejściowego aż i tym delim.

+0

-47 jest prawidłową liczbą całkowitą, ale nie jest prawidłowym wiekiem. Więc test jest zepsuty. – trojanfoe

+0

, więc powinien dwukrotnie to sprawdzić.Jak już powiedziałem, sprawdza ważność jako liczbę całkowitą nie jako wiek. – deepmax

0

std::numeric_limits pozwala uzyskać maksymalną liczbę, która zmieści się w danym typie.

W twoim przykładzie jest przekazywana do funkcji ignore(), co w zasadzie oznacza ignorowanie każdego znaku nowej linii z góry.

+0

Co z "std :: stream"? –

+0

Jest to typ używany do przechowywania danych w strumieniu. [To jest naprawdę łatwe do znalezienia] (http://en.cppreference.com/w/cpp/io/streamsize). –

1
while ((std::cout << "How old are you? ")  && !(std::cin >> age)) 

cout jest globalnym obiektu klasy ostream i cin jest globalnym obiektu klasy istream

obiekty te są stosowane wraz przeciążonych operatorów << (określonych w ostream) i >> (zdefiniowane w istream) i pobierz dane wejściowe (wywołując funkcje zdefiniowane dla tych operatorów)

Typ zwrotu operator<< jest typu ostream&, a ten z operator>> to istream&. Następnie są one konwertowane na wartości logiczne. Zobacz this.

Sprawdź this zbyt dla cin.ignore() i cin.clear()

+0

Proszę nie linkować do 'cplusplus.com'. –

+0

@bartek, Yeps osobiście nie podoba mi się, ale potem nie mogłem znaleźć właściwej strony na cpprefrence. Zaktualizuje ją, gdy ją otrzymam, Och, cóż, zrobiłeś to. Thanx –

+0

@BartekBanachewicz Co jest nie tak z cpluscplus.com? Czy mają błędne informacje? (Nie wiem, naprawdę pytam.) – Chani