Что будет если в программе ввести в строку ввода не число

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

ФлагНазначение
goodbit Всё в порядке
badbit Произошла какая-то фатальная ошибка (например, программа попыталась прочитать после конца файла)
eofbit Поток достиг конца файла
failbit Произошла нефатальная ошибка (например, пользователь ввел буквы, когда программа ожидала целое число)

Хотя эти флаги находятся в ios_base , но поскольку ios является производным от ios_base , а ios требует меньше ввода текста, чем ios_base , доступ к ним обычно осуществляется через него (например, как std::ios::failbit ).

ios также предоставляет ряд функций-членов для удобного доступа к этим состояниям:

Функция-членНазначение
good() Возвращает true , если установлен goodbit (поток в норме)
bad() Возвращает true , если установлен badbit (произошла фатальная ошибка)
eof() Возвращает true , если установлен eofbit (поток находится в конце файла)
fail() Возвращает true , если установлен failbit (произошла нефатальная ошибка)
clear() Очищает все флаги и восстанавливает поток в состояние goodbit
clear(state) Очищает все флаги и устанавливает флаг состояния, переданный в параметре
rdstate() Возвращает текущие установленные флаги
setstate(state) Устанавливает флаг состояния, переданный в параметре

Fortran. Ввод-вывод данных в строку

Чаще всего мы имеем дело failbit , который устанавливается, когда пользователь вводит недопустимые входные данные. Например, рассмотрим следующую программу:

std::cout > age;

Обратите внимание, что эта программа ожидает, что пользователь введет целое число. Однако если пользователь вводит нечисловые данные, такие как » Alex «, cin не сможет извлечь что-либо для переменной возраста age , и будет установлен бит отказа failbit .

Если такая ошибка возникает, и для потока устанавливается значение, отличное от goodbit , дальнейшие операции с этим потоком будут проигнорированы. Это условие можно устранить, вызвав функцию clear() .

Проверка корректности входных данных

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

При проверке строки мы принимаем весь пользовательский ввод как строку, а затем принимаем или отклоняем эту строку в зависимости от того, правильно ли она отформатирована. Например, если мы просим пользователя ввести номер телефона, мы можем проверить, что вводимые данные содержат десять цифр. В большинстве языков (особенно в скриптовых языках, таких как Perl и PHP) это делается с помощью регулярных выражений. Стандартная библиотека C++ также имеет библиотеку регулярных выражений. Регулярные выражения медленны по сравнению с проверкой строк вручную, и их следует использовать только в том случае, если производительность (время компиляции и время выполнения) не вызывает беспокойства, или ручная проверка слишком обременительна.

#6. Функции print() и input(). Преобразование строк в числа int() и float() | Python для начинающих

При числовой проверке мы обычно заботимся о том, чтобы число, вводимое пользователем, находилось в определенном диапазоне (например, от 0 до 20). Однако, в отличие от проверки строк, пользователь может вводить вещи, которые вообще не являются цифрами, и нам также необходимо обрабатывать эти случаи.

Чтобы помочь нам, C++ предоставляет ряд полезных функций, которые мы можем использовать для определения того, являются ли конкретные символы цифрами или буквами. В заголовке cctype находятся следующие функции:

ФункцияНазначение
std::isalnum(int) Возвращает ненулевое значение, если параметр представляет собой букву или цифру.
std::isalpha(int) Возвращает ненулевое значение, если параметр представляет собой букву.
std::iscntrl(int) Возвращает ненулевое значение, если параметр является управляющим символом.
std::isdigit(int) Возвращает ненулевое значение, если параметр является цифрой.
std::isgraph(int) Возвращает ненулевое значение, если параметр является печатным символом, который не является пробелом.
std::isprint(int) Возвращает ненулевое значение, если параметр является печатным символом (включая пробелы).
std::ispunct(int) Возвращает ненулевое значение, если параметр не является ни буквенно-цифровым, ни пробельным символом.
std::isspace(int) Возвращает ненулевое значение, если параметр – пробельный символ.
std::isxdigit(int) Возвращает ненулевое значение, если параметр является шестнадцатеричной цифрой (0-9, a-f, A-F).
Читайте также:
Программы в которых нужно уметь работать

Проверка строки

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

С этого момента мы будем использовать функции, которые (пока) не описаны в этой серии статей. Если вы хорошо разбираетесь в C++, возможно, вы сможете понять, что делают эти функции, исходя из их названий и того, как они используются. Советуем посмотреть эти новые функции и типы в справочнике, чтобы лучше понять, что они делают, и для чего еще их можно использовать.

Давайте рассмотрим простой случай проверки строки, попросив пользователя ввести свое имя. Нашим критерием проверки будет то, что пользователь вводит только буквенные символы или пробелы. Если встретится что-то еще, ввод будет отклонен.

Когда дело доходит до входных данных переменной длины, лучший способ проверить строку (помимо использования библиотеки регулярных выражений) – это пройти по всем символам строки и убедиться, что они соответствует критериям проверки. Это именно то, что мы собираемся здесь сделать, или, лучше сказать, то, что std::all_of сделает для нас.

#include // std::all_of #include // std::isalpha, std::isspace #include #include #include bool isValidName(std::string_view name) < return std::ranges::all_of(name, [](char ch) < return (std::isalpha(ch) || std::isspace(ch)); >); // До C++20, без диапазонов ranges // return std::all_of(name.begin(), name.end(), [](char ch) < // return (std::isalpha(ch) || std::isspace(ch)); // >); > int main() < std::string name<>; do < std::cout while (!isValidName(name)); std::cout

Обратите внимание, что этот код не идеален: пользователь мог сказать, что его имя » asf w jweo s di we ao «, или какая-то другая тарабарщина, или, что еще хуже, просто несколько пробелов. Мы могли бы решить эту проблему, уточнив наши критерии проверки, чтобы принимать только строки, содержащие хотя бы один символ и не более одного пробела.

Теперь давайте рассмотрим другой пример, в котором мы попросим пользователя ввести свой номер телефона. В отличие от имени пользователя, которое имеет переменную длину и критерии проверки одинаковы для каждого символа, номер телефона имеет фиксированную длину, но критерии проверки различаются в зависимости от положения символа. Следовательно, для валидации нам необходим другой подход. В этом случае мы собираемся написать функцию, которая будет проверять данные, введенные пользователем, на соответствие заранее определенному шаблону, чтобы увидеть, соответствует ли они ему. Шаблон будет работать следующим образом:

Итак, если мы спрашиваем функцию, соответствует ли строка шаблону » (###) ###-#### «, это означает, что мы ожидаем, что пользователь введет символ ‘ ( ‘, три цифры, символ ‘ ) ‘, пробел, три числа, дефис и еще четыре числа. Если что-либо из этого не совпадает, ввод будет отклонен.

Проверка чисел

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

Давайте попробуем такой подход:

#include #include int main() < int age<>; while (true) < std::cout > age; if (std::cin.fail()) // извлечение не производилось < // сбрасываем биты состояния обратно в goodbit, // чтобы мы могли использовать ignore() std::cin.clear(); // очищаем недопустимый ввод из потока std::cin.ignore(std::numeric_limits::max(), ‘n’); // попробовать снова continue; > if (age std::cout

Читайте также:
Как согласовать программу в ростехнадзоре

Если пользователь вводит число, cin.fail() вернет false , и мы перейдем к инструкции break , выходя из цикла. Если пользователь вводит данные, начинающиеся с буквы, cin.fail() вернет true , и мы перейдем к условному выражению.

Однако есть еще один случай, который мы не проверили, и это когда пользователь вводит строку, которая начинается с цифр, но затем содержит буквы (например, » 34abcd56 «). В этом случае начальные числа (34) будут извлечены в переменную age , а остаток строки (» abcd56 «) останется во входном потоке, и бит отказа НЕ будет установлен. Это вызывает две потенциальные проблемы:

  1. если вы хотите, чтобы это был допустимый ввод, теперь в вашем потоке есть мусор;
  2. если вы не хотите, чтобы это был допустимый ввод, он не отклоняется (и в вашем потоке есть мусор);

Решим первую проблему. Это просто:

#include #include int main() < int age<>; while (true) < std::cout > age; if (std::cin.fail()) // извлечение не производилось < // сбрасываем биты состояния обратно в goodbit, // чтобы мы могли использовать ignore() std::cin.clear(); // очищаем недопустимый ввод из потока std::cin.ignore(std::numeric_limits::max(), ‘n’); // попробовать снова continue; > // очищаем любой дополнительный ввод из потока std::cin.ignore(std::numeric_limits::max(), ‘n’); if (age std::cout

Если вы не хотите, чтобы такие данные были допустимыми, нам придется проделать небольшую дополнительную работу.

К счастью, предыдущее решение помогает нам в этом. Мы можем использовать функцию gcount() , чтобы определить, сколько символов было проигнорировано. Если наш ввод был допустимым, gcount() должна вернуть 1 (отброшенный символ новой строки). Если она возвращает больше 1, пользователь ввел что-то, что не было извлечено правильно, и мы должны попросить его ввести новые данные. Ниже показан пример этого:

#include #include int main() < int age<>; while (true) < std::cout > age; if (std::cin.fail()) // извлечение не производилось < // сбрасываем биты состояния обратно в goodbit, // чтобы мы могли использовать ignore() std::cin.clear(); // очищаем недопустимый ввод из потока std::cin.ignore(std::numeric_limits::max(), ‘n’); // попробовать снова continue; > // очищаем любой дополнительный ввод из потока std::cin.ignore(std::numeric_limits::max(), ‘n’); if (std::cin.gcount() > 1) // если мы удалили более одного дополнительного символа < continue; // будем считать этот ввод недопустимым >if (age break; > std::cout

Проверка чисел в виде строки

В приведенном выше примере потребовалось довольно много работы, чтобы просто получить простое значение! Другой способ обработки числовых входных данных – прочитать их как строку, а затем попытаться преобразовать в переменную числового типа. Следующая программа использует этот метод:

#include // std::from_chars #include #include #include #include std::optional extractAge(std::string_view age) < int result<>; auto end< age.data() + age.length() >; // Пытаемся извлечь int из строки age if (std::from_chars(age.data(), end, result).ptr != end) < return <>; > if (result ; > return result; > int main() < int age<>; while (true) < std::cout ; std::cin >> strAge; if (auto extracted< extractAge(strAge) >) < age = *extracted; break; >> std::cout

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

Как видите, проверка ввода в C++ – это большая работа. К счастью, многие такие задачи (например, выполнение проверки чисел в виде строки) можно легко превратить в функции, которые можно повторно использовать в самых разных ситуациях.

Источник: radioprog.ru

Что будет если в программе ввести в строку ввода не число

Здравствуйте. У меня вопрос. Как можно организовать в языке Си проверку на ввод числа т.е. если мы введем букву или иные символы вместо числа то должно выдать ошибку.
Заранее спасибо.

Читайте также:
Какие программы не работают без Гугл сервисов

Белик Виталий 🙂
Регистрация: 23.07.2007
Сообщений: 57,792

Переведи строку в число. Если функция перевода вернет ошибку значит нужно уведомить пользователя. Функций перевода в число множество — выбирай какая по вкусу из хелпа своего компилятора..

I’m learning to live.
Регистрация: 14.08.2012
Сообщений: 3

Не знаю по поводу перевода строки в число. А нету способа полегче?
Вот нашел на просторах интернета этот способ но не могу понять как он работает?
Сможет кто нибудь объяснить принцип его работы.

void main()
Белик Виталий 🙂
Регистрация: 23.07.2007
Сообщений: 57,792

Эта функция умеет возвращать в качестве результата код ошибки, если введенное нельзя сравнить с шаблоном формата. Короче если введенное не является числом по формату %d (т.е. не целое) то выдать ошибку.
Можно и так, если scanf-ом не брезгуешь.

I’m learning to live.

Источник: www.programmersforum.ru

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

Если данные вводятся в формы — то правильный путь — использование валидаторов. Если данные считываются с файла в 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

Источник: pro-prof.com

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru