dq_zhx@163.com 发表于 2014-5-21 22:57:08

atoi和itoa函数及负数转正数时溢出问题

首先贴出c函数库里的atoi函数, 其实是atol函数, 因为atoi调用了atol函数. 函数很简单,相信大家一看就懂.isspace函数是判断传入字符是否为空白符, 空白符指空格, 水平制表, 垂直制表, 换页, 回车和换行符.函数首先跳过空白字符, 之后判断正负号, 判断完正负号后判断字符是否为数字, 如果是则循环, 直到遇到非数字为止, 如果第一次循环就不是数字则直接返回 total ,此时 total为 0.atoi函数:



[*]/***
[*]*long atol(char *nptr) - Convert string to long
[*]*
[*]*Purpose:
[*]*       Converts ASCII string pointed to by nptr to binary.
[*]*       Overflow is not detected.
[*]*
[*]*Entry:
[*]*       nptr = ptr to string to convert
[*]*
[*]*Exit:
[*]*       return long int value of the string
[*]*
[*]*Exceptions:
[*]*       None - overflow is not detected.
[*]*
[*]*******************************************************************************/
[*]
[*]long __cdecl atol(
[*]      const char *nptr
[*]      )
[*]{
[*]      int c;            /* current char */
[*]      long total;         /* current total */
[*]      int sign;         /* if '-', then negative, otherwise positive */
[*]
[*]      /* skip whitespace */
[*]      while ( isspace((int)(unsigned char)*nptr) )
[*]            ++nptr;
[*]
[*]      c = (int)(unsigned char)*nptr++;
[*]      sign = c;         /* save sign indication */
[*]      if (c == '-' || c == '+')
[*]            c = (int)(unsigned char)*nptr++;    /* skip sign */
[*]
[*]      total = 0;
[*]
[*]      while (isdigit(c)) {
[*]            total = 10 * total + (c - '0');   /* accumulate digit */
[*]            c = (int)(unsigned char)*nptr++;    /* get next char */
[*]      }
[*]
[*]      if (sign == '-')
[*]            return -total;
[*]      else
[*]            return total;   /* return result, negated if necessary */
[*]}
[*]
[*]
[*]int __cdecl atoi(
[*]      const char *nptr
[*]      )
[*]{
[*]      return (int)atol(nptr);
[*]}



关于itoa函数, 我会贴出三个版本, 第一个是网上找的, 第二个是c函数库里的, 第三个我自己写的(利用<<c陷阱和缺陷>>里的一段代码改的).
版本1:
view plaincopyview plaincopyhttps://code.csdn.net/assets/CODE_ico.pnghttps://code.csdn.net/assets/ico_fork.svg



[*]char * itoa_modified( int    val,
[*]                      char*buf,
[*]                      int    radix )
[*]{
[*]    char *p, *firstdig;
[*]    char temp;            /* temp char */
[*]
[*]    p = buf;
[*]    if ( val < 0 ) {
[*]      *p++ = '-';
[*]    }
[*]    if ( val > 0 ) {
[*]      val = -val;
[*]    }
[*]    firstdig = p;
[*]    do {
[*]      *p++ = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[-( val % radix )];
[*]      val = val / radix;
[*]    } while ( val );
[*]    *p-- = '\0';
[*]    do {
[*]      temp = *p;
[*]      *p = *firstdig;
[*]      *firstdig = temp; /* swap *p and *firstdig */
[*]      --p;
[*]      ++firstdig; /* advance to next two digits */
[*]    } while ( firstdig < p ); /* repeat until halfway */
[*]    return ( buf );
[*]}


这里如果val是正数则将它转换为负数, 之后统一按负数处理. 这样就不会出现溢出问题了.

oggplay 发表于 2014-5-21 23:03:14

本帖最后由 oggplay 于 2014-5-21 23:14 编辑

The atoi() function has been deprecated by strtol() and should not beused in new code.

NAME
   atoi — convert ASCII string to integer

LIBRARY
   Standard C Library (libc, -lc)

SYNOPSIS
   #include <stdlib.h>

   int
   atoi(const char *nptr);

DESCRIPTION
   The atoi() function converts the initial portion of the string pointed to
   by nptr to int representation.

   It is equivalent to:

         (int)strtol(nptr, (char **)NULL, 10);

   The atoi() function has been deprecated by strtol() and should not be
   used in new code.

ERRORS
   The function atoi() need not affect the value of errno on an error.

SEE ALSO
   atof(3), atol(3), strtod(3), strtol(3), strtoul(3)

STANDARDS
   The atoi() function conforms to ISO/IEC 9945-1:1990 (“POSIX.1”), ISO/IEC
   9899:1990 (“ISO C90”), and ISO/IEC 9899:1999 (“ISO C99”).
NAME
   strtol, strtoll, strtoimax, strtoq — convert a string value to a long,
   long long, intmax_t or quad_t integer

LIBRARY
   Standard C Library (libc, -lc)

SYNOPSIS
   #include <stdlib.h>
   #include <limits.h>

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

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

   #include <inttypes.h>

   intmax_t
   strtoimax(const char * restrict nptr, char ** restrict endptr, int base);

   #include <sys/types.h>
   #include <stdlib.h>
   #include <limits.h>

   quad_t
   strtoq(const char *nptr, char **endptr, int base);

DESCRIPTION
   The strtol() function converts the string in nptr to a long value.The
   strtoll() function converts the string in nptr to a long long value.The
   strtoimax() function converts the string in nptr to an intmax_t value.
   The strtoq() function converts the string in nptr to a quad_t value.The
   conversion is done according to the given base, which must be between 2
   and 36 inclusive, or be the special value 0.

   The string may begin with an arbitrary amount of white space (as deter‐
   mined by isspace(3)) followed by a single optional ‘+’ or ‘-’ sign.If
   base is zero or 16, the string may then include a “0x” prefix, and the
   number will be read in base 16; otherwise, a zero base is taken as 10
   (decimal) unless the next character is ‘0’, in which case it is taken as
   8 (octal).

   The remainder of the string is converted to a long, long long, intmax_t
   or quad_t value in the obvious manner, stopping at the first character
   which is not a valid digit in the given base.(In bases above 10, the
   letter ‘A’ in either upper or lower case represents 10, ‘B’ represents
   11, and so forth, with ‘Z’ representing 35.)

   If endptr is not NULL, strtol() stores the address of the first invalid
   character in *endptr.If there were no digits at all, however, strtol()
   stores the original value of nptr in *endptr.(Thus, if *nptr is not
   ‘\0’ but **endptr is ‘\0’ on return, the entire string was valid.)

RETURN VALUES
   The strtol(), strtoll(), strtoimax() and strtoq() functions return the
   result of the conversion, unless the value would underflow or overflow.
   If no conversion could be performed, 0 is returned and the global vari‐
   able errno is set to EINVAL (the last feature is not portable across all
   platforms).If an overflow or underflow occurs, errno is set to ERANGE
   and the function return value is clamped according to the following ta‐
   ble.

         Function       underflow    overflow
         strtol()       LONG_MIN   LONG_MAX
         strtoll()      LLONG_MIN    LLONG_MAX
         strtoimax()    INTMAX_MIN   INTMAX_MAX
         strtoq()       LLONG_MIN    LLONG_MAX

ERRORS
            The value of base is not supported or no conversion
                        could be performed (the last feature is not portable
                        across all platforms).

            The given string was out of range; the value converted
                        has been clamped.

SEE ALSO
   atof(3), atoi(3), atol(3), strtod(3), strtonum(3), strtoul(3), wcstol(3)

STANDARDS
   The strtol() function conforms to ISO/IEC 9899:1990 (“ISO C90”).The
   strtoll() and strtoimax() functions conform to ISO/IEC 9899:1999
   (“ISO C99”).The BSD strtoq() function is deprecated.
页: [1]
查看完整版本: atoi和itoa函数及负数转正数时溢出问题