C++ символ для int
Что происходит, когда вы cin>> буква в переменную int? Я попробовал простой код, чтобы добавить 2 числа int, сначала прочитайте их, а затем добавьте их. Но когда я ввожу букву, она просто выходит из строя и выводит на экран тонны цифр. Но что вызывает эту ошибку? Я имею в виду, я ожидал, что он загрузит и использует ASCII-код этой буквы.
5 ответов
Я предполагаю, что у вас есть такой код:
int n;
while (someCondition) {
std::cin >> n;
.....
std::cout << someOutput;
}
Когда вы вводите что-то, что не может быть прочитано как целое число, поток (std::cin) входит в состояние сбоя, и все последующие попытки ввода терпят неудачу, пока вы не справитесь с ошибкой ввода.
Вы можете проверить успешность операции ввода:
if (!(std::cin >> n)) //failed to read int
и вы можете восстановить поток в хорошем состоянии и отбросить необработанные символы (вход, вызвавший сбой ввода):
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Другая возможность - принять входные данные в строковую переменную (которая редко дает сбой) и попытаться преобразовать строку в int.
Это очень распространенная проблема с вводом, и здесь и в других местах должно быть множество тем.
Если вы явно приведете свой символ к типу int, он будет использовать код ASCII, иначе он не будет сам приводить к типу int, поэтому вы получите странные результаты, которые вы получаете.
Проблема заключается в том, что при чтении в целочисленную переменную с использованием потоков C++ метод ввода ожидает символы, которые могут составлять число, например "+", "-", "0"... "9". Любой символ, который не входит в этот набор, завершает ввод, и из этих символов создается число.
Чтобы получить значение ASCII символа, вам нужно ввести данные в char
переменная. Внутренне он имеет значение ASCII (при условии, что программа не читает 16-битные символы или EBCDIC). Если вы хотите увидеть значение ASCII, вам необходимо вывести char
переменная как целое число (обычно требующее приведения перед выводом).
Если не удается прочитать целое число, ваша программа должна сообщить пользователю, что ввод был неверным. Программа может потребовать от пользователя ввода номера еще раз, прежде чем программа сможет обработать введенные данные.
Когда вы делаете что-то вроде:
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)
), если вы хотите продолжить расследование.