strtol используя errno - PullRequest
       8

strtol используя errno

1 голос
/ 25 февраля 2012

У меня есть следующий код:

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

void main(void)
{
     int data;
     char * tmp;
     data = strtol("23ef23",&tmp,10);
     printf("%d",errno);
     getchar();
}

вывод равен 0 ...

почему?

Я использую Visual Studio 2010 C ++ код должен быть совместим с C89.

Ответы [ 4 ]

22 голосов
/ 25 февраля 2012

strtol только устанавливает errno для условий переполнения, а не для индикации ошибок разбора.Для этого вам нужно проверить значение указателя конца, но вам нужно сохранить указатель на исходную строку:

char const * const str = "blah";
char const * endptr;

int n = strtol(str, &endptr, 0);

if (endptr == str) { /* no conversion was performed */ }

else if (*endptr == '\0') { /* the entire string was converted */ }

else { /* the unconverted rest of the string starts at endptr */ }

Я думаю, что единственными необходимыми значениями ошибки являются переполнение и переполнение.

И наоборот, если вся строка была использована в преобразовании, у вас есть *endptr = '\0', что может быть дополнительной вещью, которую вы, возможно, захотите проверить.

3 голосов
/ 25 февраля 2012

Ваша логика не соответствует «спецификации». см это Недопустимое значение не обязательно устанавливает 'errno'.

(копия следует)
long int strtol (const char * str, char ** endptr, int base);

Преобразовать строку в длинное целое Анализирует строку C str, интерпретируя ее содержимое как целое число указанной базы, которое возвращается как длинное значение типа int.

Функция сначала отбрасывает столько пробельных символов, сколько необходимо, пока не будет найден первый непробельный символ. Затем, начиная с этого символа, принимает максимально возможное количество символов, допустимых в соответствии с синтаксисом, который зависит от базового параметра, и интерпретирует их как числовое значение. Наконец, указатель на первый символ, следующий за целочисленным представлением в str, сохраняется в объекте, указанном endptr.

Если значение base равно нулю, ожидаемый синтаксис аналогичен синтаксису целочисленных констант, который образован последовательностью:

Дополнительный знак плюс или минус Необязательный префикс, указывающий восьмеричное или шестнадцатеричное основание («0» или «0x» соответственно)
Последовательность десятичных цифр (если не указан базовый префикс) или восьмеричные или
шестнадцатеричные цифры, если присутствует определенный префикс

Если базовое значение находится в диапазоне от 2 до 36, ожидаемый формат для целого числа представляет собой последовательность действительных цифр и / или букв, необходимых для представления целых чисел указанного радиуса (начиная с '0' и до 'z '/' Z 'для оснований 36). Последовательности может предшествовать знак плюс или минус и, если основание равно 16, необязательный префикс «0x» или «0X».

Если первая последовательность непробельных символов в str не является действительным целым числом, как определено выше, или если такой последовательности не существует, потому что либо str пуст или содержит только пробельные символы, преобразование не выполняется.

Параметры
ул C строка, содержащая представление целого числа. endptr Ссылка на объект типа char *, значение которого устанавливается функцией на следующий символ в строке после числового значения. Этот параметр также может быть нулевым указателем, в этом случае он не используется.

Возвращаемое значение
В случае успеха функция возвращает преобразованное целое число как длинное значение типа int. Если действительное преобразование не может быть выполнено, возвращается нулевое значение. Если правильное значение находится вне диапазона представимых значений, LONG_MAX или Возвращается LONG_MIN, а глобальной переменной errno задано значение ERANGE.

3 голосов
/ 25 февраля 2012

Вы должны установить errno в 0, прежде чем позвонить strtol. В противном случае вы перезаписываете любое значение strtol, установив errno в.

1 голос
/ 25 февраля 2012

Вы должны проверить, tmp не совпадает с "blablabla" указателем.

Если data == 0 и tmp == "blablabla", то входные данные имеют неправильный формат. errno не нужно устанавливать реализацией, если входные данные не в ожидаемом формате.

Вкл. strtol, strtoll, strtoul и strtoull функции C говорят:

(C99, 7.20.1.4p7) Если подчиненная последовательность пуста или не имеет ожидаемой формы, преобразование не выполняется; значение nptr хранится в объекте, на который указывает endptr, при условии, что endptr не является нулевым указателем.

(C99, 7.20.1.4p9) Функции strtol, strtoll, strtoul и strtoull возвращают преобразованные значение, если есть. Если преобразование не может быть выполнено, возвращается ноль.

...