atol () v / s. strtol () - PullRequest
       34

atol () v / s. strtol ()

58 голосов
/ 25 сентября 2010

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

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

long atol(const char *nptr);

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

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

Ответы [ 7 ]

83 голосов
/ 25 сентября 2010

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 может подойти только для очень простых и контролируемых случаев.

20 голосов
/ 25 сентября 2010
Функциональные возможности

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

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

18 голосов
/ 08 ноября 2012

Согласно справочной странице 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 голосов
/ 25 сентября 2010

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

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

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

4 голосов
/ 25 сентября 2010

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

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

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

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

2 голосов
/ 25 сентября 2010

Если память служит, 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" */
1 голос
/ 05 декабря 2012

Справочная страница 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).

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

#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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...