Подтвердить что ты не робот

Atol() v/s. strtol()

В чем разница между atol() и strtol()?

Согласно их справочным страницам, они, похоже, имеют тот же эффект, что и соответствующие аргументы:

long atol(const char *nptr);

long int strtol(const char *nptr, char **endptr, int base);

В обобщенном случае, когда я не хочу использовать аргумент base (у меня есть только десятичные числа), какую функцию я должен использовать?

4b9b3361

Ответ 1

strtol предоставляет вам большую гибкость, поскольку он действительно может сказать вам, была ли вся строка преобразована в целое или нет. atol, когда невозможно преобразовать строку в число (например, в atol("help")), возвращает 0, что неотличимо от atol("0"):

int main()
{
  int res_help = atol("help");
  int res_zero = atol("0");

  printf("Got from help: %d, from zero: %d\n", res_help, res_zero);
  return 0;
}

Выходы:

Got from help: 0, from zero: 0

strtol будет указывать, используя аргумент endptr, где преобразование завершилось с ошибкой.

int main()
{
  char* end;
  int res_help = strtol("help", &end, 10);

  if (!*end)
    printf("Converted successfully\n");
  else
    printf("Conversion error, non-convertible part: %s", end);

  return 0;
}

Выходы:

Conversion error, non-convertible part: help

Поэтому для любого серьезного программирования я определенно рекомендую использовать strtol. Это немного более сложно использовать, но это имеет вескую причину, как я объяснил выше.

atol может быть пригодным только для очень простых и контролируемых случаев.

Ответ 2

Функциональность

atol - это подмножество strtol функциональности, за исключением того, что atol предоставляет вам непригодные возможности обработки ошибок. Наиболее заметной проблемой с функциями ato... является то, что они приводят к поведению undefined в случае переполнения. Примечание: это не просто отсутствие информационной обратной связи в случае ошибки, это поведение undefined, то есть, как правило, невосстанавливаемый сбой.

Это означает, что функция atol (как и все другие функции ato..) практически бесполезна для любых серьезных практических целей. Это была ошибка дизайна, и ее место находится на свалке истории C. Вы должны использовать функции из группы strto... для выполнения преобразований. Они были введены, среди прочего, для исправления проблем, присущих функциям группы ato....

Ответ 3

В соответствии с man-страницей atoi она устарела strtol.

IMPLEMENTATION NOTES
The atoi() and atoi_l() functions have been deprecated by strtol() and strtol_l() 
and should not be used in new code.

Ответ 4

В новом коде я всегда использовал бы strtol. Он имеет обработку ошибок, а аргумент endptr позволяет вам видеть, какая часть строки была использована.

Стандарт C99 описывает функции ato*:

За исключением поведения при ошибке, они эквивалентны

atoi: (int)strtol(nptr,(char **)NULL, 10)
atol: strtol(nptr,(char **)NULL, 10)
atoll: strtoll(nptr, (char **)NULL, 10)

Ответ 5

atol(str) эквивалентно

strtol(str, (char **)NULL, 10);

Используйте strtol, если вы хотите, чтобы конечный указатель (чтобы проверить, есть ли больше символов для чтения или если вы вообще его прочитали) или базы, отличной от 10. В противном случае atol это нормально.

Ответ 6

Если используется память, strtol() имеет дополнительное преимущество, чтобы установить (необязательно) endptr, чтобы указать на первый символ, который не может быть преобразован. Если NULL, оно игнорируется. Таким образом, если вы обрабатываете строку, содержащую числа и символы, смешанные, вы можете продолжить.

например.

char buf[] = "213982 and the rest";
char *theRest;
long int num = strtol(buf, &theRest, 10);
printf("%ld\n", num);    /* 213982 */
printf("%s\n", theRest); /* " and the rest" */

Ответ 7

Страница man strtol дает следующее:

ERRORS
   EINVAL (not in C99) The given base contains an unsupported value.
   ERANGE The resulting value was out of range.
   The implementation may also set errno to EINVAL in case no conversion was performed (no digits seen, and 0 returned).

Следующий код проверяет ошибки диапазона. (Измененный код Eli немного)

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

int main()
{
   errno = 0;
   char* end = 0;
   long res = strtol("83459299999999999K997", &end, 10);

   if(errno != 0)
   {
      printf("Conversion error, %s\n", strerror(errno));
   }
   else if (*end)
   {
      printf("Converted partially: %i, non-convertible part: %s\n", res, end);
   }
   else
   {
      printf("Converted successfully: %i\n", res);
   }

   return 0;
}