Cin fail c что это
Перейти к содержимому

Cin fail c что это

  • автор:

cin.ignore; cin.clear; cin.fail

Потоковые обьекты, такие как cin и cout , также как и любой другой обьект, имеют определенное состояние. Для них состояние оценивается установкой определенных бит, goodbit (установлен по умолчанию и имеет нулевое значение), badbit, failbit . Если по какой то причине поток «сломался», то установится badbit , и программа аварийно завершится. Если была попытка чтения типа, но невозможно читать его из буфера, то устанавливается состояние failbit .

  1. std::cin.fail() будет означать: да, установлен failbit , поэтому любая попытка читать дальше, будет безуспешным. std::cin будет ждать очистки всех установленных битов состояния.
  2. Это делается функцией std::cin.clear , вызов которого приводит к обнулению всех битов состояния, а это и есть goodbit . Только после этого можем попытаться читать что то другое. Если мы решили, что в таком случаи(раз не было там числа) нужно пропустить строку и попытаться читать число в новой строке, то мы даем команду «игнорировать»(читать, но оставлять в буфере) много символов, пока не встретим символ перевода строки.
  3. std::cin.ignore(32767,’\n’); и есть эта команда(вместо 32767 может быть любая большая цифра такая, что точно больше, чем количество символов до ‘\n’)

Отслеживать
ответ дан 29 фев 2020 в 19:47
AR Hovsepyan AR Hovsepyan
15.9k 3 3 золотых знака 13 13 серебряных знаков 30 30 бронзовых знаков

    Важное на Мете
Похожие

Подписаться на ленту

Лента вопроса

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

Дизайн сайта / логотип © 2023 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2023.10.27.43697

Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.

7.16 – std::cin и обработка недопустимого ввода

Большинство программ, имеющих какой-либо пользовательский интерфейс, должны обрабатывать вводимые пользователем данные. В программах, которые мы писали, мы использовали std::cin , чтобы попросить пользователя ввести текст. Поскольку ввод текста имеет произвольную форму (пользователь может вводить что угодно), пользователю очень легко ввести данные, которые не ожидаются.

При написании программ вы всегда должны учитывать, как пользователи (непреднамеренно или наоборот) будут использовать ваши программы некорректно. Хорошо написанная программа будет предвидеть, как пользователи будут использовать ее неправильно, и либо аккуратно обработает эти случаи, либо вообще предотвратит их появление (если это возможно). Программа, которая хорошо обрабатывает случаи ошибок, называется надежной.

В этом уроке мы подробно рассмотрим способы, которыми пользователь может вводить недопустимые текстовые данные через std::cin , и покажем вам несколько разных способов обработки таких случаев.

std::cin , буферы и извлечение

Чтобы обсудить, как std::cin и operator>> могут давать сбой, сначала полезно немного узнать, как они работают.

Когда мы используем operator>> для получения пользовательского ввода и помещения его в переменную, это называется «извлечением». Соответственно, в этом контексте оператор >> называется оператором извлечения.

Когда пользователь вводит данные в ответ на операцию извлечения, эти данные помещаются в буфер внутри std::cin . Буфер (также называемый буфером данных) – это просто часть памяти, отведенная для временного хранения данных, пока они перемещаются из одного места в другое. В этом случае буфер используется для хранения пользовательских входных данных, пока они ожидают извлечения в переменные.

При использовании оператора извлечения происходит следующая процедура:

  • Если во входном буфере уже есть данные, то для извлечения используются они.
  • Если входной буфер не содержит данных, пользователя просят ввести данные для извлечения (так бывает в большинстве случаев). Когда пользователь нажимает Enter , во входной буфер помещается символ ‘\n’ .
  • operator>> извлекает столько данных из входного буфера, сколько может, в переменную (игнорируя любые начальные пробельные символы, такие как пробелы, табуляции или ‘\n’ ).
  • Любые данные, которые не могут быть извлечены, остаются во входном буфере для следующего извлечения.

Извлечение завершается успешно, если из входного буфера извлечен хотя бы один символ. Любые неизвлеченные входные данные остаются во входном буфере для дальнейшего извлечения. Например:

int x<>; std::cin >> x;

Если пользователь вводит «5a» , 5 будет извлечено, преобразовано в целое число и присвоено переменной x . А «a\n» останется во входном потоке для следующего извлечения.

Извлечение не выполняется, если входные данные не соответствуют типу переменной, в которую они извлекаются. Например:

int x<>; std::cin >> x;

Если бы пользователь ввел ‘b’ , извлечение не удалось бы, потому что ‘b’ не может быть извлечено в переменную типа int .

Проверка ввода

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

Есть три основных способа проверки ввода:

  • встроенный (по мере печати пользователя):
    • прежде всего, не позволить пользователю вводить недопустимые данные;
    • позволить пользователю ввести в строку всё, что он хочет, затем проверить правильность строки и, если она корректна, преобразовать строку в окончательный формат переменной;
    • позволить пользователю вводить всё, что он хочет, позволить std::cin и operator>> попытаться извлечь данные и обработать случаи ошибок.

    Некоторые графические пользовательские интерфейсы и расширенные текстовые интерфейсы позволяют проверять входные данные, когда пользователь их вводит (символ за символом). В общем случае, программист предоставляет функцию проверки, которая принимает входные данные, введенные пользователем, и возвращает true , если входные данные корректны, и false в противном случае. Эта функция вызывается каждый раз, когда пользователь нажимает клавишу. Если функция проверки возвращает истину, клавиша, которую только что нажал пользователь, принимается. Если функция проверки возвращает false , введенный пользователем символ отбрасывается (и не отображается на экране). Используя этот метод, вы можете гарантировать, что любые входные данные, вводимые пользователем, гарантированно будут корректными, потому что любые недопустимые нажатия клавиш обнаруживаются и немедленно отбрасываются. Но, к сожалению, std::cin не поддерживает этот стиль проверки.

    Поскольку строки не имеют никаких ограничений на ввод символов, извлечение гарантированно завершится успешно (хотя помните, что std::cin прекращает извлечение на первом неведущем пробельном символе). После того, как строка введена, программа может проанализировать эту строку, чтобы узнать, корректна она или нет. Однако анализ строк и преобразование вводимых строк в другие типы (например, числа) может быть сложной задачей, поэтому это делается только в редких случаях.

    Чаще всего мы позволяем std::cin и оператору извлечения выполнять эту тяжелую работу. В этом методе мы позволяем пользователю вводить всё, что он хочет, заставляем std::cin и operator>> попытаться извлечь данные и справиться с последствиями, если это не удастся. Это самый простой способ, о котором мы поговорим ниже.

    Пример программы

    Рассмотрим следующую программу-калькулятор, в которой нет обработки ошибок:

    #include double getDouble() < std::cout ; std::cin >> x; return x; > char getOperator() < std::cout ; std::cin >> op; return op; > void printResult(double x, char operation, double y) < switch (operation) < case '+': std::cout > int main() < double x< getDouble() >; char operation< getOperator() >; double y< getDouble() >; printResult(x, operation, y); return 0; >

    Эта простая программа просит пользователя ввести два числа и математический оператор.

    Enter a double value: 5 Enter one of the following: +, -, *, or /: * Enter a double value: 7 5 * 7 is 35

    Теперь подумайте, где неверный ввод пользователя может нарушить работу этой программы.

    Сначала мы просим пользователя ввести несколько чисел. Что, если он введет что-то, отличающееся от числа (например, ‘q’ )? В этом случае извлечение не удастся.

    Во-вторых, мы просим пользователя ввести один из четырех возможных символов. Что, если он введет символ, отличный от ожидаемых? Мы сможем извлечь входные данные, но пока не обрабатываем то, что происходит после.

    В-третьих, что, если мы попросим пользователя ввести символ, а он введет строку типа «*q hello» . Хотя мы можем извлечь нужный нам символ ‘*’ , в буфере останутся дополнительные входные данные, которые могут вызвать проблемы в будущем.

    Типы недопустимых входных текстовых данных

    Обычно мы можем разделить ошибки ввода текста на четыре типа:

    1. извлечение входных данных выполняется успешно, но входные данные не имеют смысла для программы (например, ввод ‘k’ в качестве математического оператора);
    2. извлечение входных данных выполняется успешно, но пользователь вводит дополнительные данные (например, вводя «*q hello» в качестве математического оператора);
    3. ошибка извлечения входных данных (например, попытка ввести ‘q’ при запросе ввода числа);
    4. извлечение входных данных выполнено успешно, но пользователь выходит за пределы значения числа.

    Таким образом, чтобы сделать наши программы устойчивыми, всякий раз, когда мы запрашиваем у пользователя ввод, мы в идеале должны определить, может ли произойти каждый из вышеперечисленных возможных вариантов, и если да, написать код для обработки этих случаев.

    Давайте разберемся в каждом из этих случаев и в том, как их обрабатывать с помощью std::cin .

    Случай ошибки 1: извлечение успешно, но входные данные не имеют смысла

    Это самый простой случай. Рассмотрим следующий вариант выполнения приведенной выше программы:

    Enter a double value: 5 Enter one of the following: +, -, *, or /: k Enter a double value: 7

    В этом случае мы попросили пользователя ввести один из четырех символов, но вместо этого он ввел ‘k’ . ‘k’ – допустимый символ, поэтому std::cin успешно извлекает его в переменную op , и она возвращается в main . Но наша программа не ожидала этого, поэтому она не обрабатывает этот случай правильно (и, таким образом, ничего не выводит).

    Решение здесь простое: выполните проверку ввода. Обычно она состоит из 3 шагов:

    1. убедитесь, что пользовательский ввод соответствует вашим ожиданиям;
    2. если да, верните значение вызывающей функции;
    3. если нет, сообщите пользователю, что что-то пошло не так, и попросите его повторить попытку.

    Вот обновленная функция getOperator() , которая выполняет проверку ввода.

    char getOperator() < while (true) // Цикл, пока пользователь не введет допустимые данные < std::cout ; std::cin >> operation; // Проверяем, ввел ли пользователь подходящие данные switch (operation) < case '+': case '-': case '*': case '/': return operation; // возвращаем символ вызывающей функции default: // в противном случае сообщаем пользователю, что пошло не так std::cout > // и попробуем еще раз >

    Как видите, мы используем цикл while для бесконечного цикла до тех пор, пока пользователь не предоставит допустимые данные. Если он этого не делает, мы просим его повторить попытку, пока он не даст нам правильные данные, не закроет программу или не уничтожит свой компьютер.

    Случай ошибки 2: извлечение успешно, но с посторонними входными данными

    Рассмотрим следующий вариант выполнения приведенной выше программы:

    Enter a double value: 5*7

    Как думаете, что будет дальше?

    Enter a double value: 5*7 Enter one of the following: +, -, *, or /: Enter a double value: 5 * 7 is 35

    Программа выводит правильный ответ, но форматирование испорчено. Давайте подробнее разберемся, почему.

    Когда пользователь вводит «5*7» в качестве вводных данных, эти данные попадают в буфер. Затем оператор >> извлекает 5 в переменную x , оставляя в буфере «*7\n» . Затем программа напечатает «Enter one of the following: +, -, *, or /:» . Однако когда был вызван оператор извлечения, он видит символы «*7\n» , ожидающие извлечения в буфере, поэтому он использует их вместо того, чтобы запрашивать у пользователя дополнительные данные. Следовательно, он извлекает символ ‘*’ , оставляя в буфере «7\n» .

    После запроса пользователя ввести другое значение double , из буфера извлекается 7 без ожидания ввода пользователя. Поскольку у пользователя не было возможности ввести дополнительные данные и нажать Enter (добавляя символ новой строки), все запросы в выводе идут вместе в одной строке, даже если вывод правильный.

    Хотя программа работает, выполнение запутано. Было бы лучше, если бы любые введенные посторонние символы просто игнорировались. К счастью, символы игнорировать легко:

    // очищаем до 100 символов из буфера или пока не будет удален символ '\n' std::cin.ignore(100, '\n');

    Этот вызов удалит до 100 символов, но если пользователь ввел более 100 символов, мы снова получим беспорядочный вывод. Чтобы игнорировать все символы до следующего символа ‘\n’ , мы можем передать std::numeric_limits::max() в std::cin.ignore() . std::numeric_limits::max() возвращает наибольшее значение, которое может быть сохранено в переменной типа std::streamsize . Передача этого значения в std::cin.ignore() приводит к отключению проверки счетчика.

    Чтобы игнорировать всё, вплоть до следующего символа ‘\n’ , мы вызываем

    std::cin.ignore(std::numeric_limits::max(), '\n');

    Поскольку эта строка довольно длинная для того, что она делает, будет удобнее обернуть ее в функцию, которую можно вызвать вместо std::cin.ignore() .

    #include // для std::numeric_limits void ignoreLine() < std::cin.ignore(std::numeric_limits::max(), '\n'); >

    Поскольку последний введенный пользователем символ должен быть ‘\n’ , мы можем указать std::cin игнорировать символы в буфере, пока не найдет символ новой строки (который также будет удален).

    Давайте обновим нашу функцию getDouble() , чтобы игнорировать любой посторонний ввод:

    double getDouble() < std::cout ; std::cin >> x; ignoreLine(); return x; >

    Теперь наша программа будет работать, как ожидалось, даже если мы введем «5*7» при первом запросе ввода – 5 будет извлечено, а остальные символы из входного буфера будут удалены. Поскольку входной буфер теперь пуст, при следующем выполнении операции извлечения данные у пользователя будут запрашиваться правильно!

    Случай ошибки 3: сбой при извлечении

    Теперь рассмотрим следующий вариант выполнения нашей программы калькулятора:

    Enter a double value: a

    Неудивительно, что программа работает не так, как ожидалось, но интересно, как она дает сбой:

    Enter a double value: a Enter one of the following: +, -, *, or /: Enter a double value: 

    и программа внезапно завершается.

    Это очень похоже на случай ввода посторонних символов, но немного отличается. Давайте посмотрим подробнее.

    Когда пользователь вводит ‘a’ , этот символ помещается в буфер. Затем оператор >> пытается извлечь ‘a’ в переменную x , которая имеет тип double . Поскольку ‘a’ нельзя преобразовать в double , оператор >> не может выполнить извлечение. В этот момент происходят две вещи: ‘a’ остается в буфере, а std::cin переходит в «режим отказа».

    Находясь в «режиме отказа», будущие запросы на извлечение входных данных будут автоматически завершаться ошибкой. Таким образом, в нашей программе калькулятора вывод запросов всё еще печатается, но любые запросы на дальнейшее извлечение игнорируются. Программа просто выполняется до конца, а затем завершается (без вывода результата потому, что мы не прочитали допустимую математическую операцию).

    К счастью, мы можем определить, завершилось ли извлечение сбоем, и исправить это:

    if (std::cin.fail()) // предыдущее извлечение не удалось? < // да, давайте разберемся с ошибкой std::cin.clear(); // возвращаем нас в "нормальный" режим работы ignoreLine(); // и удаляем неверные входные данные >

    Давайте, интегрируем это в нашу функцию getDouble() :

    double getDouble() < while (true) // Цикл, пока пользователь не введет допустимые данные < std::cout ; std::cin >> x; if (std::cin.fail()) // предыдущее извлечение не удалось? < // да, давайте разберемся с ошибкой std::cin.clear(); // возвращаем нас в "нормальный" режим работы ignoreLine(); // и удаляем неверные входные данные >else // иначе наше извлечение прошло успешно < ignoreLine(); return x; // поэтому возвращаем извлеченное нами значение >> >

    Примечание. До C++11 неудачное извлечение не приводило к изменению извлекаемой переменной. Это означает, что если переменная была неинициализирована, она останется неинициализированной в случае неудачного извлечения. Однако, начиная с C++11, неудачное извлечение из-за недопустимого ввода приведет к тому, что переменная будет инициализирована нулем. Инициализация нулем означает, что для переменной установлено значение 0, 0.0, «» или любое другое значение, в которое 0 преобразуется для этого типа.

    Случай ошибки 4: извлечение успешно, но пользователь выходит за пределы значения числа

    Рассмотрим следующий простой пример:

    #include #include int main() < std::int16_t x<>; // x - 16 бит, может быть от -32768 до 32767 std::cout > x; std::int16_t y<>; // y - 16 бит, может быть от -32768 до 32767 std::cout > y; std::cout

    Что произойдет, если пользователь введет слишком большое число (например, 40000)?

    Enter a number between -32768 and 32767: 40000 Enter another number between -32768 and 32767: The sum is: 32767

    В приведенном выше случае std::cin немедленно переходит в «режим отказа», но также присваивает переменной ближайшее значение в диапазоне. Следовательно, x остается с присвоенным значением 32767. Дополнительные входные данные пропускаются, оставляя y с инициализированным значением 0. Мы можем обрабатывать этот вид ошибки так же, как и неудачное извлечение.

    Примечание. До C++11 неудачное извлечение не приводило к изменению извлекаемой переменной. Это означает, что если переменная была неинициализирована, в случае неудачного извлечения она останется неинициализированной. Однако, начиная с C++11, неудачное извлечение вне диапазона приведет к тому, что переменной будет присвоено ближайшее значение в диапазоне.

    Собираем всё вместе

    Вот наш пример калькулятора с полной проверкой ошибок:

    #include #include void ignoreLine() < std::cin.ignore(std::numeric_limits::max(), '\n'); > double getDouble() < while (true) // Цикл, пока пользователь не введет допустимые данные < std::cout ; std::cin >> x; // Проверяем на неудачное извлечение if (std::cin.fail()) // предыдущее извлечение не удалось? < // да, давайте разберемся с ошибкой std::cin.clear(); // возвращаем нас в "нормальный" режим работы ignoreLine(); // и удаляем неверные входные данные std::cout else < ignoreLine(); // удаляем любые посторонние входные данные // пользователь не может ввести бессмысленное значение double, // поэтому нам не нужно беспокоиться о его проверке return x; >> > char getOperator() < while (true) // Цикл, пока пользователь не введет допустимые данные < std::cout ; std::cin >> operation; ignoreLine(); // Проверяем, ввел ли пользователь осмысленные данные switch (operation) < case '+': case '-': case '*': case '/': return operation; // возвращаем символ вызывающей функции default: // в противном случае сообщаем пользователю, что пошло не так std::cout > // и попробуем еще раз > void printResult(double x, char operation, double y) < switch (operation) < case '+': std::cout > int main() < double x< getDouble() >; char operation< getOperator() >; double y< getDouble() >; printResult(x, operation, y); return 0; >

    Заключение

    При написании программы подумайте о том, как пользователи будут неправильно использовать вашу программу, особенно при вводе текста. Для каждой точки ввода текста учтите:

    • Могло ли извлечение закончиться неудачей?
    • Может ли пользователь ввести больше, чем ожидалось?
    • Может ли пользователь ввести бессмысленные входные данные?
    • Может ли пользователь переполнить входные данные?

    Вы можете использовать операторы if и булеву логику, чтобы проверить, являются ли входные данные ожидаемыми и осмысленными.

    Следующий код очистит любые посторонние входные данные:

    std::cin.ignore(std::numeric_limits::max(), '\n');

    Следующий код будет проверять и исправлять неудачные извлечения или переполнение:

    if (std::cin.fail()) // предыдущее извлечение не удалось или закончилось переполнением? < // да, давайте разберемся с ошибкой std::cin.clear(); // возвращаем нас в "нормальный" режим работы ignoreLine(); // и удаляем неверные входные данные >

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

    Примечание автора

    Проверка ввода важна и полезна, но она также делает примеры более сложными и трудными для понимания. Соответственно, на будущих уроках мы, как правило, не будем проводить никакой проверки вводимых данных, если они не имеют отношения к чему-то, чему мы пытаемся научить.

    Некорректная работа cin.fail() при вводе смешанных данных

    Дарова, у меня есть код, где присутствует проверка на ввод неправильных данных(в моем случае всяких букв), но работает она не так, как мне бы хотелось. У меня пользователь должен ввести стоимость детали, и у меня, как я уже сказал, есть проверка на ввод неправильных данных (букв), но дело в том, что если я ввожу СНАЧАЛА цифры какие-то, а ПОТОМ буквы, то программа думает, что ошибок нету и пропускает дальше. Так вот, как мне сделать так, чтобы программа искала в вводе данных любой намек на буквы и не пропускала дальше?
    Вот код:

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
    #include #include #include #include struct part { std::string name; double cost; }; int main() { const int size = 4; part apart[size]; std::cout  "==============================================================================="  "\n\n"; for (int i = 0; i  size; i++) { std::cout  "Enter the name of part number "  i + 1  ": "; std::getline(std::cin, apart[i].name); enterConst: std::cout  "Enter the price of '"  apart[i].name  "' $: "; std::cin >> apart[i].cost; if (std::cin.fail()) { std::cin.clear(); std::cin.ignore(std::numeric_limitsstd::streamsize>::max(), '\n'); goto enterConst; } std::cin.ignore(std::numeric_limitsstd::streamsize>::max(), '\n'); } std::cout  "\n\n==============================================================================="  "\n\n"; for (int i = 0; i  size; i++) { std::cout  "Part number "  i + 1  ":\n"; std::cout  "Name: "  apart[i].name  std::endl; std::cout  "Cost: $ "  apart[i].cost  std::endl; std::cout  "\n==============================================================================="  "\n"; } _getch(); }

    Проверка вводимых потоковых данных С++

    Если данные вводятся в формы — то правильный путь — использование валидаторов. Если данные считываются с файла в JSON/XML форматах используйте JSON-схему или XSD/DTD. Ну а эта инструкция посвящена работе с потоками типа cin, ifstream.

    Валидация ввода чисел

    Итак, мы считали целое число с консоли:

    int a; cin >> a;

    Что если пользователь ввел не целое число или строку? При этом поднимется флаг ошибки потока cin. Не вдаваясь в подробности, проверить его можно функцией cin.fail() . Но нам надо не просто проверить, а попросить пользователя ввести данные еще раз. Перед следующей попыткой ввода надо снять флаг ошибки функцией cin.clear() и удалить все находящиеся в нем данные. Для удаления данных можно использовать такую конструкцию: cin.ignore(cin.rdbuf()->in_avail()); или такую: cin.sync(); тут функция rdbuf возвращет буфер, а in_avail — количество байт в нем. Однако, это работает не всегда (не во всех компиляторах), in_avail часто возвращает некорректные значения. Вместо этого можно передать в ignore любое большое число, задающее число байт, которые надо пропустить. Удобен и переносим такой вариант: std::cin.ignore(std::numeric_limits::max(), ‘\n’); Итого, чтобы считать целое число используем такую конструкцию:

    int a; cin >> a; while (cin.fail())< cin.clear(); std::cin.ignore(std::numeric_limits::max(), '\n'); cout > a; >

    Валидация ввода строки

    Допустим, мы думаем, что в файле находится строка не более чем из N символов. Считаем ее так:

    char s1[N]; cin.getline(s1, N,'\n');

    Что может пойти не так? — На самом деле, мы считываем строку не более чем из N символов или до символа перевода строки. Если перед этим мы считали с клавиатуры число (например как описано выше) — то в буфере остается символ перевода строки, так как оператор >> не удаляет его из потока. Часто для этого выполняют что-то типа cin.get() , однако более надежно вызвать что-то типа std::cin.ignore(std::numeric_limits::max(), ‘\n’); Ну а что если пользователь ввел строку из более чем N символов? Проблема в том, что сама собой она не обрежется, а самое главное — в этом случае поднимется флаг ошибки ( cin.fail ) и любое последующее обращение к потоку сломает вашу программу. итак, мы пришли к такому варианту:

    char s1[N]; std::cin.ignore(std::numeric_limits::max(), '\n'); cin.getline(s1, N,'\n'); if (cin.fail()) < cin.clear(); std::cin.ignore(std::numeric_limits::max(), '\n'); >

    Этот вариант считывает с потока строку (не более чем из N символов), а остальные — игнорирует (до символа перевода строки). Однако, если вы хотите при некорректном ввода попросить пользователя ввести данные повторно, используйте такой вариант:

    char s1[N]; std::cin.ignore(std::numeric_limits::max(), ‘\n’); cin.getline(s1, N,’\n’); while (cin.fail()) < cin.clear(); std::cin.ignore(std::numeric_limits::max(), '\n'); cout

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *