cout << "Enter the number: ";
int number;
if (cin >> number)
{
// throw away the rest of the line
char c;
while (cin.get(c) && c != '\n')
if (!std::isspace(c))
{
std::cerr << "ERROR unexpected character '" << c << "' found\n";
exit(EXIT_FAILURE);
}
cout << "Enter names: ";
string name;
// keep getting lines until EOF (or "bad" e.g. error reading redirected file)...
while (getline(cin, name))
...use name...
}
else
{
std::cerr << "ERROR reading number\n";
exit(EXIT_FAILURE);
}
В приведенном выше коде этот бит ...
char c;
while (cin.get(c) && c != '\n')
if (!std::isspace(c))
{
std::cerr << "ERROR unexpected character '" << c << "' found\n";
exit(EXIT_FAILURE);
}
... проверяет оставшуюся строку ввода после того, как число содержит только пробел.
Почему бы и нетпросто используйте ignore?
Это довольно многословно, поэтому использование ignore
в потоке после >> x
- это часто рекомендуемый альтернативный способ отбросить контент до следующей новой строки, но он рискует выбросить незаполненные пробелысодержание и при этом, пропуская поврежденные данные в файле.Вы можете или не можете заботиться, в зависимости от того, является ли содержимое файла надежным, насколько важно избегать обработки поврежденных данных и т. Д.
Так когда бы вы использовали очистку и игнорирование?
Итак,std::cin.clear()
(и std::cin.igore()
) не требуется для этого, но полезен для устранения состояния ошибки.Например, если вы хотите дать пользователю много шансов ввести действительный номер.
int x;
while (std::cout << "Enter a number: " &&
!(std::cin >> x))
{
if (std::cin.eof())
{
std::cerr << "ERROR unexpected EOF\n";
exit(EXIT_FAILURE);
}
std::cin.clear(); // clear bad/fail/eof flags
// have to ignore non-numeric character that caused cin >> x to
// fail or there's no chance of it working next time; for "cin" it's
// common to remove the entire suspect line and re-prompt the user for
// input.
std::cin.ignore(std::numeric_limits<std::streamsize>::max());
}
Разве это не может быть проще с пропусками или аналогичными?
Еще одна простая, но недоделанная альтернатива ignore
для вашего первоначального требования - использовать std::skipws
, чтобы пропустить любое количествопробела перед чтением строк ...
if (std::cin >> number >> std::skipws)
{
while (getline(std::cin, name))
...
... но если он получит ввод наподобие "1E6" (например, какой-то ученый пытается ввести 1 000 000, но C ++ поддерживает только эти обозначения для чисел с плавающей запятой)Если вы не согласитесь с этим, вы получите number
, установленное на 1
, и E6
, прочитанное как первое значение name
.Отдельно, если у вас есть действительный номер, за которым следуют одна или несколько пустых строк, эти строки будут игнорироваться.