Sfname
@Sfname

Почему в C++ после несоответствия введенных данных определённому типу программа завершается?

Здравствуйте.
Есть такой код:
string name = "?"; int age = 1;
while(cin>>name>>age);
string answer = "?";
cout << "Введите что-то там: ";
cin >> answer;

Если пользователь введёт строку там, где требуется целое число, программа завершается, минуя cin>>answer.
Почему так?
  • Вопрос задан
  • 212 просмотров
Решения вопроса 1
myjcom
@myjcom Куратор тега C++
Почему так?

см. комментарий

А вообще раздели потоки
ответственность.

#include<iostream>
#include<string>
#include<sstream>
using namespace std;

struct Entry
{
  string name;
  int age;
};

istream& operator>>(istream& is, Entry& e)
{
  is >> e.name >> e.age;
  return is;
}

ostream& operator<<(ostream& os, Entry& e)
{
  os << e.name << " " << e.age;
  return os;
}

int main()
{  
  string line;

  getline(cin, line);
  istringstream is(line);

  is.exceptions(ios_base::failbit);

  Entry e;
  try // I know it was wrong.
  {
    while(is >> e)
    {
      cout << e << "\n";
    }
  }
  catch(exception& e)
  {
    cerr << e.what() << endl;
  }

  cout << "Done!\n";

  string answer;
  cin >> answer;

  system("pause");
}

Ответ написан
Пригласить эксперта
Ответы на вопрос 2
@oleg_ods
Добавь условие выхода из цикла. У тебя while бесконечный, поэтому до cout не доходит
Ответ написан
@QuickWind
Суть следующая:
Когда функция форматированного ввода-вывода получает неверные данные она устанавливает failbit потока, что сигнализирует об ошибке (когда "cin>>age;" получает букву, например).
Когда этот поток используется в дальнейшем, то прежде проверяется его состояние, если stream.good() != true, то это признак произошедшей ошибки.
Для работы с потоками используется класс sentry, который проверяет его состояние перед использованием, например:
std::istream::sentry s(cin);
if (s) {
	// работаем дальше
} else {
	// ошибка!
}

В вашем примере на строке:
cin >> answer;
sentry(cin) == false, поэтому работа с потоком прерывается. К тому же после такого прерывания работы функции, в потоке остаётся хвост непрочитанных данных, который будет читаться следующими вызовами чтения и это надо учитывать.
Таким образом, в данном случае необходимо использовать обработку ошибок, например:
#include <limits>

if (cin.eof() || cin.bad()) {
	// Обработать при необходимости!
}
if (cin.fail()){
	cin.clear();
	cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

Обработчик сбрасывает биты ошибок и игнорирует мусорные данные до конца строки.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
22 сент. 2019, в 10:34
10 руб./за проект
22 сент. 2019, в 09:39
3500 руб./за проект