Atoi - как определить разницу между нулем и ошибкой?
http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/
Возвращаемое значение
При успешном выполнении функция возвращает преобразованное целое число как значение int
.
Если действительное преобразование не было выполнено, возвращается нулевое значение.
Если правильное значение выходит за пределы диапазона отображаемых значений, возвращается INT_MAX или INT_MIN.
Итак, как я отличаюсь между atoi("poop")
и atoi("0")
и atoi("0000000")
Да, я могу выполнить цикл и проверить все нули в случае, если я получаю 0 результат, но не лучший способ?
Примечание. Я использую ANSI C89
Ответы
Ответ 1
Одна из причин atoi
иногда считается небезопасной. Вместо этого используйте strtol
/strtoul
. И если вы используете его strtonum
.
Функция atoi
более опасна, чем вы думаете. В стандарте POSIX
говорится:
Если значение не может быть представлено, поведение undefined.
В стандарте C99 также говорится:
7.20.1
Функции atof, atoi, atol и atoll не должны влиять на значение целочисленное выражение errno при ошибке. Если значение результата не может быть представлено, поведение не определено.
Ответ 2
Как описано @cnicutar и @ouah, atoi
не может отличить допустимое значение 0 от недопустимой строки, что делает лучшие параметры семейства strtol
.
Но Почему? и Как?. Сначала убедитесь, что оба atoi
и strtol
преобразуют только начальный набор чисел в строку в числовые значения. Любые конечные нечисловые символы просто игнорируются. strtol
может использоваться для проверки недопустимых строк, поскольку в дополнение к числовому значению он также возвращает указатель на конец числовой части строки. Таким образом, если этот указатель end
по-прежнему относится к началу исходной строки, вы можете сказать, что произошла ошибка, и никакие символы из строки не были преобразованы.
Есть несколько других тонкостей, как показано в примере кода:
long lnum;
int num;
char *end;
errno = 0;
lnum = strtol(in_str, &end, 10); //10 specifies base-10
if (end == in_str) //if no characters were converted these pointers are equal
fprintf(stderr, "ERROR: can't convert string to number\n");
//If sizeof(int) == sizeof(long), we have to explicitly check for overflows
if ((lnum == LONG_MAX || lnum == LONG_MIN) && errno == ERANGE)
fprintf(stderr, "ERROR: number out of range for LONG\n");
//Because strtol produces a long, check for overflow
if ( (lnum > INT_MAX) || (lnum < INT_MIN) )
fprintf(stderr, "ERROR: number out of range for INT\n");
//Finally convert the result to a plain int (if that what you want)
num = (int) lnum;
Примечание. Если вы уверены, что входная строка будет в пределах допустимого интервала int, вы можете исключить lnum
и просто направить strtol return напрямую: num = (int) strtolen(in_str, &end, 10);
Ответ 3
Вы не можете.
atoi
не может обнаружить ошибки. Если результат не может быть представлен, atoi
вызывает поведение undefined. Используйте strtol
вместо atoi
.
Защищенная CERT-кодировка рекомендует использовать strtol
вместо atoi
, читать:
INT06-C. Используйте strtol() или связанную функцию для преобразования токена строки в целое число
Ответ 4
Я использовал
#include <stdlib.h>
using namespace std;
до main и без проблем при использовании atoi, но будьте осторожны, он не может обнаружить переполнение или неправильные входы. используя strtol немного сложно и проверьте этот для получения дополнительной информации