2013-04-26 2 views
8

Я нашел эту ссылку на http://www.parashift.com/c++-faq-lite/istream-and-ignore.htmlC++ Пример: Невозможно понять, что делается?

, который показывает «Как я могу получить std :: cin, чтобы пропустить недопустимые символы ввода?»

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 

Я не могу понять, как это делается> Может ли кто-нибудь объяснить, пожалуйста?

У меня есть сомнения с:

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

Как это проверить действительную запись? Я хочу попросить выражения: «std :: cout < <« Сколько вам лет? »И«! (Std :: cin >> age) », верните true или false, которые являются ANDed?

другая вещь, которая это заблуждение является использование,

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

Что есть цель? Искал на Google об этих функциях, но до сих пор я не ясно. в частности, std::numeric_limits<std::streamsize>::max()

Может ли один помочь? Спасибо

+0

cin.clear() и cin.ignore() для предотвращения КИН для пропуску, (если не ошибаюсь). Во-первых, я думаю, это неправильно, когда вас спрашивают. – cakil

ответ

10

Операторы вставки и извлечения << и >> в потоках возвращают ссылку на поток. Вот почему вы можете нанизывать вставки, как так:

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

Первый std::cout << "Hello, " возвращает ссылку на std::cout, а затем у вас есть эквивалент std::cout << "World!".

Потоки также могут быть преобразованы в bool. Это в основном проверяет, что состояние потока все еще в порядке. Ничего не удалось. Например, вы могли бы сделать это:

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

Это будет проверять, если std::cin поток все еще находится в хорошем состоянии.

Теперь давайте посмотрим на код, который вы спросили о:

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

Включение в std::cout не вызовет сбой. Единственная причина, по которой он включен, заключается в том, что он возникает каждый раз перед входом в age. Альтернативой было бы разместить его один раз перед while и один раз в конце корпуса while.

После того, как будет введено значение std::cout, будет оценен !(std::cin >> age). Сначала это позволит пользователю предоставить age. Тогда две вещи могут случиться:

  1. Если это не удается каким-то образом (пользователь может ввести символы, а не целое число), то обязательно будет установлен бит. Это означает, что результат std::cin >> age будет преобразован в bool, который будет false. ! инвертирует его на true. Так как и первое, и второе условие было истинным, тело цикла while будет выполняться, сообщая пользователю, что они ввели недопустимое значение, и цикл снова повторится.

  2. если вход успешно, результат std::cin >> age будет true и ! превратит его в false. Это означает, что тело цикла while не будет выполняться и не сообщит пользователю, что они ввели неправильное значение.

Теперь давайте посмотрим на:

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

Это происходит только в случае, если 1 выше, когда вход не удалось. Если поток переходит в состояние сбоя, он не будет принимать никаких вложений или выделений до тех пор, пока состояние не будет очищено. вот что clear(). Затем вызов в ignore говорит, чтобы извлечь все символы до и включить следующий \n в поток и отбросить их. Это избавляет от недопустимого ввода потока.

+0

«Тогда вызов игнорировать говорит, чтобы извлечь все символы до следующего \ n в потоке и отбросить их. Это избавится от недопустимого ввода из потока». - это означает, что символ новой строки '\ n' все еще находится в потоке, не так ли '\ n' в качестве входа в следующую итерацию «Как вы стары?» –

+0

@GauravK Извините, это должно быть «вплоть до следующего' \ n' ». –

+0

Нет, я просто хочу знать, игнорирует ли игнорировать(), что я читал, что если Delim - это EOF, он не отбрасывается, если он отличается от EOF - он извлекается и отбрасывается тоже? –

0

Как age представляет собой целое

(std::cin >> age) 

пытается разобрать вход, чтобы получить действительное целое число, если он может возвращать верно, в противном случае возвращает ложь.

Чтобы узнать о cin.ignore, он будет ..

Экстракты и отбрасывает символы из входного потока до тех пор, пока включая DELIM.

+0

-47 - действительное целое число, но не действительный возраст. Таким образом, тест не работает. – trojanfoe

+0

так, он должен проверить его дважды.Как я уже сказал, он проверяет справедливость как целое число, а не возраст. – deepmax

0

std::numeric_limits позволяет получить максимальное число, которое может вписываться в данный тип.

В вашем примере это передано в функцию ignore(), что в основном означает игнорирование каждого символа новой строки.

+0

Как насчет «std :: streamsize»? –

+0

Это тип, используемый для хранения данных в потоке. [Это действительно легко найти] (http://en.cppreference.com/w/cpp/io/streamsize). –

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

cout является глобальным объектом класса ostream и cin является глобальным объектом класса istream

Эти объекты используются вдоль перегруженных операторов << (определенных в ostream) и >> (определено в istream), чтобы (путем вызова функций, определенных для этих операторов)

Тип возврата operator<< имеет тип ostream& и номер operator>> является istream&. Затем они преобразуются в логические значения. См. this.

Проверить this тоже для cin.ignore() и cin.clear()

+0

Пожалуйста, не связывайтесь с 'cplusplus.com'. –

+0

@bartek, Yeps я лично не люблю их, но потом не смог найти подходящую страницу на cpprefrence. Обновит его, как только я получу его, ну, ты сделал это. Thanx –

+0

@BartekBanachewicz Что не так с cpluscplus.com? У них неправильная информация? (Я не знаю, я действительно спрашиваю.) – Chani