2015-03-30 2 views
2

У меня есть следующий код:Различие в значениях atoi

char* input = (char*)malloc(sizeof(char) * BUFFER) // buffer is defined to 100 
int digit = atoi(input); // convert char into a digit 
int digit_check = 0; 
digit_check += digit % 10; // get last value of digit 

При запуске вход 1234567896 и точно так же цифра = 1234567896 и digit_check = 6.

Однако, когда я бегу вход 9999999998, digit = 1410065406 и поэтому digit_check = 6, когда это должно быть 8.

Для второго примера, почему существует разница между вводом и цифрой, когда она должна быть того же значения?

+3

Вам нужно выяснить максимальное значение, которое int может хранить на вашей платформе. – nos

+0

@nos Только что узнал об этом, спасибо. –

+2

sizeof (char) по определению. Вы можете безопасно использовать «malloc (BUFFER)». В C вы также можете исключить возвращаемое значение malloc(). – Jack

ответ

4

atoi ограничен размером int (32 бита на последней пластине).

Если вы хотите обрабатывать большие номера, вы можете использовать atol или scanf("%ld").

Не забудьте ввести свою переменную в long int (или long).


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

+1

И максимальное значение, подписанное 32-битовое целое (с использованием дополнения 2), может содержать 2147483647. – 5gon12eder

+0

@ blue112 Спасибо за быстрый и понятный ответ, который будет отмечен как ответ, как только он позволит мне –

+0

@ 5gon12eder: Собственно говоря, свойства положительного поддиапазона со знаком целочисленных типов не зависят от подписанного представления. То есть «Дополнение 2» не имеет к этому никакого отношения. – AnT

6

Возможно, потому что 9999999998 больше, чем максимальное (подписанное) целочисленное представление, поэтому вы получаете переполнение.

На самом деле это двоичное представление 9999999998 и 1410065406:

10 01010100 00001011 11100011 11111110 
    01010100 00001011 11100011 11111110 

Как вы можете увидеть, если вы видите 1410065406 является 32ed битового значения 9999999998

1

На многих платформах размера int ограничен на 4 байта, что ограничивает цифру в [-2 ** 31, 2**31 - 1].

Использование long (или long long) с strtol (или strtoll) в зависимости от платформы вы строите для. Например, GCC на x86 будет иметь 64-битный long long, а для amd64 он будет иметь 64-битные и long long.

Итак:

long long digit = strtoll(input, NULL, 10); 

Примечание: strtoll() популярен в Unix-подобных системах и стал стандартом в C++ 11, а не реализации всех VC++ есть. Используйте _strtoi64() вместо:

__int64 digit = _strtoi64(input, NULL, 10); 
0

Вы, вероятно, хотите использовать функцию atoll, которая возвращает long long int, то есть в два раза больше, как int (скорее всего 64 бита в вашем случае).

Он объявлен в stdlib.h

http://linux.die.net/man/3/atoll

0

Вы должны избегать называть atoi на неинициализированной строке, если нет \0 на шпагате, вы утратившие читать и иметь ошибку сегментации. Вместо этого вы должны использовать strtoimax, это более безопасно.

0

99999999988 больше, чем максимальное значение, которое может представлять целое число. Использовать либо atol() OR atoll()

0

Вы должны прекратить использовать функцию atoi или любые другие функции от ato... группы. Эти функции официально не устарели, но они фактически прекращены с 1995 года и существуют только для целей совместимости с устаревшим кодом. Забудьте об этих функциях, как будто их не существует. Эти функции не обеспечивают полезную обратную связь в случае ошибки или переполнения. И переполнение - это то, что, по-видимому, происходит в вашем примере.

Для преобразования строк в числа, стандартная библиотека C предоставляет функцию strtol и другие функции от strto... группы. Это функции, которые вы должны использовать для выполнения преобразования. И не забудьте проверить результат для переполнения: strto... функции обеспечивают эту обратную связь через возвращаемое значение и переменную errno.