鱼C论坛

 找回密码
 立即注册
查看: 7439|回复: 1

[技术交流] atoi和itoa函数及负数转正数时溢出问题

[复制链接]
发表于 2014-5-21 22:57:08 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x

首先贴出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:
[cpp] view plaincopyview plaincopy

                               
登录/注册后可看大图

                               
登录/注册后可看大图



  • 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是正数则将它转换为负数, 之后统一按负数处理. 这样就不会出现溢出问题了.
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-5-21 23:03:14 | 显示全部楼层
本帖最后由 oggplay 于 2014-5-21 23:14 编辑

The atoi() function has been deprecated by strtol() and should not be  used 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
     [EINVAL]           The value of base is not supported or no conversion
                        could be performed (the last feature is not portable
                        across all platforms).

     [ERANGE]           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.
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-27 02:21

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表