Есть несколько проблем с вашим кодом.Во-первых, вы не проверяете, что ваш ввод был успешным;правильное условие для while
должно быть:
while ( !cin || (*race < 1 || *race > 3) )
Как написано, если ввод не удался (что происходит при вводе '.'
, предполагая, что race
имеет тип int*
), тогда *race
содержит его предыдущее значение, каким бы оно ни было.
Во-вторых, если вы получаете ошибку от cin
, вы не очищаете ее.Когда поток находится в состоянии ошибки, он остается таким до тех пор, пока вы не очистите его явно.Если cin
потерпел неудачу, вам нужно выполнить:
cin.clear();
где-нибудь в цикле.
Третье, что если cin
не удастся, вы не извлечете символ, которыйсделал это не удалось, так что после очистки состояния ошибки, вам нужно извлечь его.Учитывая то, как вы структурировали свой диалог, вы, вероятно, захотите игнорировать все до конца строки:
cin.ignore( INT_MAX, '\n' );
Возможно, вы захотите сделать это, даже если cin
не потерпел неудачу, либо вцикл (если введен из-за условия *race < 1 || *race > 3
) или в случае успеха.В качестве альтернативы вы можете перейти к чтению строк и убедиться, что строка содержит только пробелы после интересующего вас символа.
Это последнее решение, которое я бы принял, поскольку оно обрабатывает почти всеиз вышеперечисленных проблем.Поэтому мой код будет выглядеть примерно так:
// return -1 on error in input,
// throw exception on (unexpected) end of file
int
getRace( std::istream& source )
{
std::string line;
if ( !std::getline( source, line ) ) {
throw std::ios_base::failure( "Unexpected end of file" );
}
std::istringstream tmp( line );
int results;
return tmp >> results >> std::ws && tmp.get() == EOF
? results
: -1;
}
// ...
int race = -1;
while ( race < 0 ) {
std::cout << "What is your race\n"
"1. Human\n"
"2. Troll\n"
"3. Zombie\n" << std::flush;
race = getRace( std::cout );
if ( race < 0 ) {
std::cout << "Wrong choice" << std::endl;
}
}
Обратите внимание, что при вводе через строку вы избегаете любых проблем с сбросом ошибок формата, пропуском ошибочного ввода или повторной синхронизацией в случае ошибки.