3. Анализ и проверка ошибок выполняются одновременно в условной части блока if
if (cin >> x >> y) {
cout << "You entered: " << x
<< " and " << y << '\n';
4. Если по какой-то причине анализ завершился ошибкой, то мы скажем пользователю об этом. Объект потока cin
cin.clear()
и отбрасываем все входные данные, полученные ранее. Отбрасывание выполняется с помощью cin.ignore
, где мы указываем, что нужно отбросить максимальное количество символов до тех пор, пока не встретим символ новой строки (который тоже будет отброшен). После этого символа снова начинаются интересные входные данные: } else {
cout << "Oh no, that did not go well!\n";
cin.clear();
cin.ignore(
std::numeric_limits
'\n');
}
5. Теперь запросим еще какие-нибудь входные данные. Мы позволим пользователю вводить имена. Они могут состоять из нескольких слов, разделенных пробелами, поэтому символ пробела не подходит в качестве разделителя. Так что воспользуемся std::getline
cin
, ссылкой на строку, в которую будут скопированы входные данные, и символом-разделителем (таковым выступит запятая ','
). Задействуя вместо cin
конструкцию cin >> ws
в качестве параметра потока для getline
, можно дать cin
команду отбросить пробелы, стоящие перед именами. На каждом шаге цикла выводим текущее имя, но если оно пустое, то завершим цикл: cout << "now please enter some "
"comma-separated names:\n> ";
for (string s; getline(cin >> ws, s, ',');) {
if (s.empty()) { break; }
cout << "name: \"" << s << "\"\n";
}
}
6. Компиляция и запуск программы дадут следующий результат (для него предполагается введение только корректных значений). Мы ввели числа "1 2"
$ ./strings_from_user_input Please Enter two numbers:
> 1 2
You entered: 1 and 2
now please enter some comma-separated names:
> john doe, ellen ripley, alice, chuck norris,,
name: "john doe"
name: "ellen ripley"
name: "alice"
name: "chuck norris"
7. При повторном запуске программы и вводе некорректных цифр в самом начале мы увидим, что программа корректно выбирает другую ветвь, отбрасывает некорректные данные и продолжает работу с помощью слушателя имен. Попробуйте использовать строки cin.clear()
cin.ignore(...)
, чтобы увидеть, как это пересекается с кодом чтения имен:$ ./strings_from_user_input
Please Enter two numbers:
> a b
Oh no, that did not go well!
now please enter some comma-separated names:
> bud spencer, terence hill,,
name: "bud spencer"
name: "terence hill"
Как это работает
В этом разделе мы выполнили сложную операцию получения входных данных. Первое, на что следует обратить внимание: получение данных и проверка на ошибки всегда происходили одновременно.
Результатом выполнения выражения cin >> x
cin
. Таким образом можно создавать конструкции наподобие cin >> x >> y >> z >> ....
В то же время можно преобразовать данные к булевым значениям, используя их в булевых контекстах, таких как условие if
. Булево значение говорит нам, была ли корректной последняя операция чтения. Вот почему можно создавать конструкции, аналогичные выражению if (cin >> x >> y){...}
.