Если cin >> num
не удалось получить недопустимый вход, необходимо удалить его из потока. Я предлагаю использовать ignore
вместо sync
для этого. Причиной является sync
is не гарантированно должен удалить оставшийся вход в все реализации стандартной библиотеки.
#include <iostream>
#include <limits>
int main()
{
int num;
while (cout << "Enter a number" && !(cin >> num))
{
cin.clear(); // clear the error
// Remove input up to a new line
cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
cout << "Invalid input; please re-enter.\n";
}
}
Приведенный выше пример использует std::numeric_limits<std::streamsize>::max()
используется для получения максимального числа символов входной буфер может содержать. Это позволяет ignore()
удалить как можно больше символов до новой строки. Это идиоматический C++ и предпочтительнее использования magic numbers, которые скорее всего скроют проблему, с которой вы в настоящее время работаете.
Это хорошо работает, но не обрабатывает ситуации, когда ввод содержит дополнительные символы после номера. Чтобы справиться с этими ситуациями, цикл необходимо немного изменить для обработки дополнительной проверки. Один из вариантов состоит в том, чтобы прочитать целую строку от cin
, поместить ее в std::stringstream
, прочитать номер из этого и затем выполнить дополнительную проверку. Существует один особый случай, который, возможно, нужно учитывать, хотя это - строка, где единственными символами после числа являются пробелы. К счастью, стандартная библиотека предоставляет модификатор потока std::skipws
, который позволяет легко обрабатывать ситуацию. В приведенном ниже примере показано, как сделать это без особого effor
#include <iostream>
#include <sstream>
int main()
{
int num;
for(;;)
{
std::cout << "Enter a number: " << std::flush;
std::string line;
std::getline(std::cin, line); // Read a line from console
std::stringstream text(line); // store in a string stream
char ch = 0;
if(!(text >> num).fail() && (text >> std::skipws >> ch).fail())
{
break;
}
std::cout << "Invalid input; please re-enter.\n";
}
return 0;
}
Выражение (text >> std::skipws >> ch).fail()
пропускает все пробелы, которые появляются после того, как числа, а затем пытается читать один символ. Если символ не доступен, чтение не будет выдаваться, если пользователь вводит только номер и ничего больше. Если мы попытаемся сделать это с помощью cin
, он будет ожидать ввода пользователем большего текста, даже если вход действителен.
Вы действительно не должны писать такой код, очень сложно понять, что происходит и где ошибка. – Djon
Подсказка: http://en.cppreference.com/w/cpp/io/basic_istream/ignore – aschepler
@Djon Я нахожу код достаточно понятным и ошибку легко обнаружить. Что именно вас беспокоит? – jrok