Когда вы делаете что-то вроде:
int x;
cin >> x;
Вы указываете C ++ ожидать чтения int
с клавиатуры. На самом деле, когда вы вводите что-то, отличное от int
, поток ввода (в данном случае стандартный ввод) становится непригодным из-за состояния ошибки.
Вот почему я лично предпочитаю всегда читать строки и при необходимости конвертировать их в числа. В части C стандартной библиотеки C ++ есть функции преобразования, которые могут помочь с этим.
double cnvtToNumber(const std::string &num)
{
char * ptr;
double toret = strtod( num.c_str(), &ptr );
if ( *ptr != 0 ) { // If it got to the end of the string, then it is correct.
throw std::runtime_error( "input was not a number" );
}
return toret;
}
Здесь вы конвертируете число и определяете, было ли преобразование правильным. strtod(s)
остановится только при нахождении конца строки или пробела. Чтобы избежать запаздывающих пробелов в функции, вам может понадобиться функция обрезки:
std::string &trim(std::string &str)
{
// Remove trailing spaces
unsigned int pos = str.length() -1;
while( str[ pos ] == ' ' ) {
--pos;
}
if ( pos < ( str.length() -1 ) ) {
str.erase( pos + 1 );
}
// Remove spaces at the beginning
pos = 0;
while( str[ pos ] == ' ' ) {
++pos;
}
if ( pos < 1 ) {
str.erase( 0, pos );
}
return str;
}
Теперь вы можете безопасно читать с консоли (или любого другого входного потока):
int main()
{
std::string entry;
try {
std::getline( std::cin, entry );
int age = cnvtToNumber( trim( entry ) );
std::cout << age << std::endl;
} catch(const std::exception &e) {
std::cerr << e.what() << std::endl;
}
}
Конечно, вы можете потерять точность, если будете всегда читать double
и затем конвертировать их. Существуют специальные функции для целых чисел (strtol(s)
), на случай, если вы захотите продолжить исследование.