Перейти к содержимому

Cin fail c что это

  • автор:

Как правильно использовать cin.fail() в c++

Я пишу программу, где получаю целочисленный ввод от пользователя с помощью cin>>iUserSel; .. Если пользователь вводит письмо, программа переходит в бесконечный цикл. Я попытался предотвратить это с помощью кода ниже, но программа переходит в бесконечный цикл и печатает «Неправильно! Введите #!». Как я могу исправить свою программу?

cin>>iUserSel; while (iValid == 1) < if (cin.fail()) < cin.ignore(); cout>iUserSel; >//closes if else iValid = 0; >//closes while 

Я нашел некоторые сведения об этом на Правильный способ использования cin.fail() и Вопрос C++ cin.fail() , но я не понял, как их использовать для решения моей проблемы.

Поделиться Источник 22 октября 2015 в 15:12

3 ответа

Когда cin не работает, вам нужно очистить флаг ошибки. В противном случае последующие операции ввода будут не операционными.

Чтобы очистить флаги ошибки, вам нужно вызвать cin.clear() .

cin >> iUserSel; while (iValid == 1) < if (cin.fail()) < cin.clear(); // clears error flags cin.ignore(); cout > iUserSel; >//closes if else iValid = 0; >//closes while 

Я также предлагаю вам изменить

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

В случае, если пользователь введет более одной буквы.

Поделиться 22 октября 2015 в 15:19

Проблема, с которой вы столкнулись, заключается в том, что вы не очищаете failbit из потока. Это делается с помощью функции clear .

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

while (!(std::cin >> iUserSel)) < // Clear errors (like the failbit flag) std::cin.clear(); // Throw away the rest of the line std::cin.ignore(std::numeric_limits::max(), '\n'); std::cout

Поделиться 22 октября 2015 в 15:20

Вот что я бы порекомендовал:

// Read the data and check whether read was successful. // If read was successful, break out of the loop. // Otherwise, enter the loop. while ( !(cin >> iUserSel) ) < // If we have reached EOF, break of the loop or exit. if ( cin.eof() ) < // exit(0); . break; >// Clear the error state of the stream. cin.clear(); // Ignore rest of the line. cin.ignore(std::numeric_limits::max(), '\n'); // Ask more fresh input. cout

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 золотых знака 14 14 серебряных знаков 30 30 бронзовых знаков

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

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

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

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

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

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

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

Cin fail c что это

Объявляет объекты, управляющие чтением из стандартных потоков и записью в них. Это часто единственный заголовок, который требуется выполнить входные и выходные данные из программы C++.

Синтаксис

#include

Библиотека использует #include операторы , #include #include и #include инструкции.

Замечания

Объекты можно разделить на две группы:

  • cin , cout , cerr и clog ориентированы на байты, выполняя обычные передачи байтов во время.
  • wcin , , wcoutwcerr и wclog широко ориентированы, переводя на широкие символы, которые программа управляет внутренне.

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

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

Однако эта гарантия не является универсальной. Статический конструктор может вызвать функцию в другой записи преобразования. Вызываемая функция не может предположить, что объекты, объявленные в этом заголовке, были созданы, учитывая неопределенный порядок, в котором единицы перевода участвуют в статической конструкции. Чтобы использовать эти объекты в таком контексте, необходимо сначала создать объект класса ios_base::Init .

Глобальные объекты потоков

Имя Описание
cerr Указывает глобальный поток cerr .
cin Указывает глобальный поток cin .
clog Указывает глобальный поток clog .
cout Указывает глобальный поток cout .
wcerr Указывает глобальный поток wcerr .
wcin Указывает глобальный поток wcin .
wclog Указывает глобальный поток wclog .
wcout Указывает глобальный поток wcout .

cerr

Объект cerr управляет выходными данными в буфер потока, связанный с объектом stderr , объявленным в .

extern ostream cerr; 
Возвращаемое значение
Замечания

Этот объект управляет вставкой без буферизации в стандартный вывод ошибок в виде байтового потока. После создания объекта выражение cerr.flags & unitbuf ненулевое и cerr.tie() == &cout . Дополнительные сведения см. здесь: cerr.flags и unitbuf .

Пример
// iostream_cerr.cpp // compile with: /EHsc #include #include using namespace std; void TestWide( ) < int i = 0; wcout > i; wcerr int main( ) < int i = 0; cout > i; cerr

cin

Указывает глобальный поток cin .

extern istream cin; 
Возвращаемое значение
Замечания

Объект контролирует получение данных из стандартного ввода, как потока байтов. После создания объекта вызов cin.tie возвращается &cout .

Пример

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

// iostream_cin.cpp // compile with: /EHsc #include using namespace std; int main() < int x; cout > x; while (x < 1 || x >4) < cout > x; // not a numeric character, probably // clear the failure and pull off the non-numeric character if (cin.fail()) < cin.clear(); char c; cin >> c; > > > 

clog

Указывает глобальный поток clog .

extern ostream clog; 
Возвращаемое значение
Замечания

Этот объект управляет вставкой с буферизацей в стандартный вывод ошибок в виде байтового потока.

Пример

См. cerr с примером использования clog .

cout

Указывает глобальный поток cout .

extern ostream cout; 
Возвращаемое значение
Замечания

Этот объект управляет вставкой в стандартный вывод в виде байтового потока.

Пример

См. cerr с примером использования cout .

wcerr

Указывает глобальный поток wcerr .

extern wostream wcerr; 
Возвращаемое значение
Замечания

Этот объект управляет вставкой без буферизации в стандартный вывод ошибок в виде двухбайтового потока. После создания объекта выражение wcerr.flags & unitbuf ненулевое. Дополнительные сведения см. здесь: wcerr.flags и unitbuf .

Пример

См. cerr с примером использования wcerr .

wcin

Указывает глобальный поток wcin .

extern wistream wcin; 
Возвращаемое значение
Замечания

Этот объект управляет извлечением из стандартного ввода в виде двухбайтового потока. После создания объекта вызов wcin.tie возвращается &wcout .

Пример

См. cerr с примером использования wcin .

wclog

Указывает глобальный поток wclog .

extern wostream wclog; 
Возвращаемое значение
Замечания

Этот объект управляет вставкой с буферизацей в стандартный вывод ошибок в виде двухбайтового потока.

Пример

См. cerr с примером использования wclog .

wcout

Указывает глобальный поток wcout .

extern wostream wcout; 
Возвращаемое значение
Замечания

Этот объект управляет вставкой в стандартный вывод в качестве широкого потока.

Пример

См. cerr с примером использования wcout .

Экземпляры CString в операторе wcout необходимо привести к const wchar_t* , как показано в следующем примере.

CString cs("meow"); wcout <<(const wchar_t*) cs < 

Дополнительные сведения см. в разделе Базовые операции CString.

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

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