Бесконечный цикл с cin при вводе строки, когда ожидается число - PullRequest
20 голосов
/ 03 мая 2011

В следующем цикле, если мы введем символы в качестве ввода cin вместо ожидаемых чисел, то он перейдет в бесконечный цикл.Может ли кто-нибудь объяснить мне, почему это происходит?

Когда мы используем cin, если ввод не число, то есть ли способы обнаружить это, чтобы избежать вышеупомянутых проблем?

unsigned long ul_x1, ul_x2;

while (1)
{
  cin >> ul_x1 >> ul_x2;
  cout << "ux_x1 is " << ul_x1 << endl << "ul_x2 is " << ul_x2 << endl;
}

Ответы [ 4 ]

27 голосов
/ 03 мая 2011

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

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

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

  if (cin.fail())
  {
     cout << "ERROR -- You did not enter an integer";

     // get rid of failure state
     cin.clear(); 

     // From Eric's answer (thanks Eric)
     // discard 'bad' character(s) 
     cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

  }

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

9 голосов
/ 03 мая 2011

Внимание

Обратите внимание на следующее решение.Это еще не все, чтобы очистить ошибку в вашем случае. Вы по-прежнему получите бесконечный цикл!

if (cin.fail())
{
     cout << "Please enter an integer";
     cin.clear();
}

Полное решение

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

if (cin.fail())
{
         cout << "Please enter an integer";
         // clear error state
         cin.clear();
         // discard 'bad' character(s)
         cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

Другое решение

Вы также можете использовать getline и stringstream для достижения.Вот краткий пример.

   string input;
   while (1)
   {
      getline(cin, input);
      stringstream(input) >> x;
      cout << x << endl;
   }
2 голосов
/ 03 мая 2011

Возможно, это потому, что

  1. cin - это функция потоковой передачи. Когда вводится нечисловое значение вместо номера, это игнорируется. И вы запрашивается повторная запись.
  2. Даже если вы дали числовые значения, вам будет предложено ввести больше входных данных, поскольку вы находитесь в бесконечном цикле.

Вы можете решить эту проблему следующим образом: 1. Создайте функцию для ввода строки. 2. вернуть его как числовое после преобразования. Используйте strtod () для конвертации.

Надеюсь, это поможет:)

0 голосов
/ 27 января 2018

Другой альтернативой является оператор! , он эквивалентен функции-члену fail ()

//from Doug's answer
if ( !cin )
{
   cout << "ERROR -- You did not enter an integer";

   // get rid of failure state
   cin.clear(); 

   // From Eric's answer (thanks Eric)
   // discard 'bad' character(s) 
   cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
...