原文:http://www.cnblogs.com/JefferyZhou/archive/2010/07/01/1769555.html

在很多时候我们都很清楚 atoX 系列函数: atoi , atol , atof
新来的一系列函数:  strtol,  strtoul, strtod 
通常有如下的关系:
1. 对应关系其中:

atoi   (把字符串转到整形)    --对应--   strtol  (把字符串转到长整形)

atol   (把字符串转到长整形)    --对应--   strtol  (把字符串转到长整形)

atof   (把字符串转到浮点数)    --对应--   strtod (把字符串转到浮点数) 
2. atoX 系列是 三十年前的函数 strtoX 系列是后十年产品

3. atoX 系列接口,没有成功失败的区别(标准实现中),    strtoX 系列接口,有成功失败的区别

比如:int i_atoi_lfs =  atoi(""); 与 int i_atoi_rfs = atoi("0"); 两个得到的是一样的,没有任何区别

而: int i_atoi_lfs =  strtol  ("", NULL,10); 与 int i_atoi_rfs = strtol  ("0", NULL,10);  得到的结果都是0,但是左边会置失败标志位。

4. msvcr80.dll  的具体实现:

1
2
3
4
5
int __cdecl atoi(__in_z const char *_Str){  return _tstoi(_Str);  }   
int __cdecl _tstoi(     const _TCHAR *nptr        ){    return (int)_tstol(nptr);}
int __cdecl _tstoi(     const _TCHAR *nptr        ){    return (int)_tstol(nptr);}
long __cdecl _tstol(const _TCHAR *nptr){return _tcstol(nptr, NULL, 10);}
#define _tcstol   strtol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<pre class="brush:cpp">extern "C" long __cdecl strtol (
        const char *nptr,
        char **endptr,
        int ibase
        )
{
    if (__locale_changed == 0)
    {
        return (long) strtoxl(&__initiallocalestructinfo, nptr, (const char **)endptr, ibase, 0);
    }
    else
    {
        return (long) strtoxl(NULL, nptr, (const char **)endptr, ibase, 0);
    }
}
</pre>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
static unsigned long __cdecl strtoxl (
        _locale_t plocinfo,
        const char *nptr,
        const char **endptr,
        int ibase,
        int flags
        )
{
        const char *p;
        char c;
        unsigned long number;
        unsigned digval;
        unsigned long maxval;
        _LocaleUpdate _loc_update(plocinfo);
 
        /* validation section */
        if (endptr != NULL)
        {
            /* store beginning of string in endptr */
            *endptr = (char *)nptr;
        }
        _VALIDATE_RETURN(nptr != NULL, EINVAL, 0L);
        _VALIDATE_RETURN(ibase == 0 || (2 <= ibase && ibase <= 36), EINVAL, 0L);
 
        p = nptr;                       /* p is our scanning pointer */
        number = 0;                     /* start with zero */
//1. 这里关注到,函数没有检查传入的原字符指针是否为空, 如果传递了一个空的就崩了....
        c = *p++;                       /* read char */
        while ( _isspace_l((int)(unsigned char)c, _loc_update.GetLocaleT()) )
            c = *p++;               /* skip whitespace */
 
//2. 不要期望能够 转换负负得正的字符串, 注意 "--100" 得到 0 ,  "-100" 得到 -100
        if (c == '-') {
            flags |= FL_NEG;        /* remember minus sign */
            c = *p++;
        }
        else if (c == '+')
            c = *p++;               /* skip sign */
//3.  基数是 2 到 36 的闭区间 , [2, 36]
        if (ibase < 0 || ibase == 1 || ibase > 36) {
            /* bad base! */
            if (endptr)
                /* store beginning of string in endptr */
                *endptr = nptr;
            return 0L;              /* return 0 */
        }
 
//4. 如果转换的时候基数输入是0, 则基数取决于原字符的前面两个字符,
// 以非0开头的是 10进制字符串,
// 以0x或者0X开头的是 16进制字符串,
// 而仅仅以 0开头的是 8进制
        else if (ibase == 0) {
            /* determine base free-lance, based on first two chars of
               string */
            if (c != '0')
                ibase = 10;
            else if (*p == 'x' || *p == 'X')
                ibase = 16;
            else
                ibase = 8;
        }
 
//  {{{   源码里面,这个地方 有这么一段 暂时不知道是干嘛的, 在我看来貌似是多余的
        if (ibase == 0) {
            /* determine base free-lance, based on first two chars of
               string */
            if (c != '0')
                ibase = 10;
            else if (*p == 'x' || *p == 'X')
                ibase = 16;
            else
                ibase = 8;
        }
//}}}
 
// 5. 如果是 16 进制,则跳过0x 或者 0X 的前缀
        if (ibase == 16) {
            /* we might have 0x in front of number; remove if there */
            if (c == '0' && (*p == 'x' || *p == 'X')) {
                ++p;
                c = *p++;       /* advance past prefix */
            }
        }
 
// 6. 下面就是读取字符串,然后按照 local 解析应用的数值, 如果在转换过程中出现各种情况都会对标志位flags 进行标记
        /* if our number exceeds this, we will overflow on multiply */
        maxval = ULONG_MAX / ibase;
 
 
        for (;;) {      /* exit in middle of loop */
            /* convert c to value */
            if ( __ascii_isdigit_l((int)(unsigned char)c, _loc_update.GetLocaleT()) )
                digval = c - '0';
            else if ( __ascii_isalpha_l((int)(unsigned char)c, _loc_update.GetLocaleT()) )
                digval = __ascii_toupper(c) - 'A' + 10;
            else
                break;
            if (digval >= (unsigned)ibase)
                break;          /* exit loop if bad digit found */
 
            /* record the fact we have read one digit */
            flags |= FL_READDIGIT;
 
            /* we now need to compute number = number * base + digval,
               but we need to know if overflow occured.  This requires
               a tricky pre-check. */
 
            if (number < maxval || (number == maxval &&
                        (unsigned long)digval <= ULONG_MAX % ibase)) {
                /* we won't overflow, go ahead and multiply */
                number = number * ibase + digval;
            }
            else {
                /* we would have overflowed -- set the overflow flag */
                flags |= FL_OVERFLOW;
                if (endptr == NULL) {
                    /* no need to keep on parsing if we
                       don't have to return the endptr. */
                    break;
                }
            }
 
            c = *p++;               /* read next digit */
        }
 
        --p;                            /* point to place that stopped scan */
 
        if (!(flags & FL_READDIGIT)) {
            /* no number there; return 0 and point to beginning of
               string */
            if (endptr)
                /* store beginning of string in endptr later on */
                p = nptr;
            number = 0L;            /* return 0 */
        }
        else if ( (flags & FL_OVERFLOW) ||
                ( !(flags & FL_UNSIGNED) &&
                  ( ( (flags & FL_NEG) && (number > -LONG_MIN) ) ||
                    ( !(flags & FL_NEG) && (number > LONG_MAX) ) ) ) )
        {
            /* overflow or signed overflow occurred */
            errno = ERANGE;                  //(老的实现方式和新的实现方式区别主要在这里, 新版友记录转换过程)
            if ( flags & FL_UNSIGNED )
                number = ULONG_MAX;
            else if ( flags & FL_NEG )
                number = (unsigned long)(-LONG_MIN);
            else
                number = LONG_MAX;
        }
 
        if (endptr != NULL)
            /* store pointer to char that stopped the scan */
            *endptr = p;
 
        if (flags & FL_NEG)
            /* negate result if there was a neg sign */
            number = (unsigned long)(-(long)number);
 
        return number;                  /* done. */
}

所以 atoi 已经等同于strtol

Sign,  Clown , 2010.07.01 . 23:32 . HDPY

[本文原创,转载请注明出处,在文章末尾提供原文链接http://www.cnblogs.com/JefferyZhou/,否则一旦发现,将按字节每人民币收费,绝不论价]

字符数字转换 atoi 与 strtol的更多相关文章

  1. 比较java与c语言中数字转换成字符的不同

    java java中将数字转换成字符非常方便,只要用一个"+"然后在跟一个空格行了.比如,你输入一个122 ,就会变成"122 ". import java.u ...

  2. Halcon中循环读取文件的实现以及数字与字符的转换

    在循环读取文件的位置时,常用到数字与字符的转换. 数字与字符的转换 将字符转换为数字 tuple_number(StringImageIndex,IntImageIndex)` 1 2 1 2 将数字 ...

  3. js将数字转换成货币形式的字符

    因为UI图上有的地方需要将数字转成货币形式的,例如:1234567转成  1,234,567  这样的,不过之前没弄过,然后在网上搜了下方法,参考了下面这篇文章 参考文章:JS将数字转成货币形式的简单 ...

  4. c语言字符串 数字转换函数大全

    最近学数据结构老是做实验 常用到字符串和数字的转换 想找却发现网上的资料太散 所以搜集整理一下 方便以后再用 atof(将字符串转换成浮点型数) atoi(将字符串转换成整型数) atol(将字符串转 ...

  5. iconv字符编码转换

    转自 http://blog.csdn.net/langresser_king/article/details/7459367 iconv(http://www.gnu.org/software/li ...

  6. unicode编码、字符的转换和得到汉字的区位码

    一:unicode编码.字符的转换截图 二:unicode编码.字符的转换代码 using System; using System.Collections.Generic; using System ...

  7. 编码问题 php字符编码转换类

    各种平台和软件打开显示的编码问题,需要使用不同的编码,根据我们不同的需求. php 字符编码转换类,支持ANSI.Unicode.Unicode big endian.UTF-8.UTF-8+Bom ...

  8. js字符串转换成数字与数字转换成字符串的实现方法

    转载:点击查看地址 js字符串转换成数字 将字符串转换成数字,得用到parseInt函数.parseInt(string) : 函数从string的开始解析,返回一个整数. 举例:parseInt(' ...

  9. js字符串转换成数字,数字转换成字符串

    转自网络,忘记出处了. js字符串转换成数字 将字符串转换成数字,得用到parseInt函数. parseInt(string) : 函数从string的开始解析,返回一个整数. 举例:parseIn ...

随机推荐

  1. 2019.4.4 盒模型&定位&浮动

    盒模型 盒模型 除了图片表单元素之外,基本所有标签都可以看做一个盒子 盒模型的要素 父子关系之间用padding 兄弟关系之间用margin margin padding border 后面跟的值的顺 ...

  2. centos7安装串口终端kermit

    1. 将usb转串口连接到PC上.通过dmesg命令可以查看USB转串口是否被PC识别.显示 ……attachec to ttyUSB0即被识别. 2. 安装kermit.     [seif@cen ...

  3. 安装Telerik JustMock插件后启动不成功

    1.打开Telerik JustMock Configuration 勾选所有框 2.到C:\Program Files (x86)\Progress\Telerik JustMock\Librari ...

  4. 2019.04.17 读书笔记 checked与unchecked

    在普通的编程中,我们是很容易去分析数据的大小,然后给出合理的类型,但是在很多数据库的累计中,缺存在很多隐患,特别是研发时,数据量小,求和也不会溢出,当程序运行几年后,再来一次大求和,隐形的BUG就出来 ...

  5. golang bufio.Scanner

    一, 我们一般会这么用,接收 标准输入的东西: scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { fmt.Println(scann ...

  6. unity动态加载FBX模型(Http下载到Rescources文件,场景Load直接调用):

    using UnityEngine; using System.Collections; using System.IO; using System.Net; using System; using ...

  7. Eclipse的简单的用法大全

    Eclipse我认为最重要的功能:断点调试 Debug的作用: 调试程序并且查看程序的执行流程 如何查看程序执行的流程 断点(就是一个标记,表示从哪里开始) 设置断点(在你想要断点的代码的左边双击即可 ...

  8. cloudera-scm-server启动时出现Caused by: javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: Could not open connection问题解决方法(图文详解)

    问题现象 查看 [root@cmbigdata1 cloudera-scm-server]# pwd /var/log/cloudera-scm-server [root@cmbigdata1 clo ...

  9. mongodb3.4 远程连接认证失败

    mongodb开启或者关闭授权功能时还是挺麻烦的,需要新建服务键入mongod --auth.为了方便,我这里是建了两个服务,用到哪个就切换至哪个服务. --需要授权 mongod --logpath ...

  10. 一站式机器学习平台TI-ONE是什么?——云+未来峰会开发者专场回顾

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 背景:5月23-24日,以“焕启”为主题的腾讯“云+未来”峰会在广州召开,广东省各级政府机构领导.海内外业内学术专家.行业大咖及技术大牛等在 ...