atoi(表示 ascii to integer)是把字符串转换成整型数的一个函数.

  atoi()函数会扫描参数 nptr字符串,跳过前面的空白字符(例如空格,tab缩进等,可以通过isspace( )函数来检测),直到遇上数字或正负符号才开始做转换,而再遇到非数字或字符串结束时('\0')才结束转换,并将结果返回。如果 nptr不能转换成 int 或者 nptr为空字符串,那么将返回0

  我们在模拟实现atoi函数时,要注意以下几点:

  1.字符串之前的空白问题  

  2.正负号

  3.字符串为空时

  4.被转换的数字过于大(正溢出、负溢出)

  5.其他,无法转换的情况(全是字母....之类的)

  我们了解atoi函数功能和一些注意事项之后,开始模拟实现它,代码如下:

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
enum{
vaild = 0,
invaild = 1
};
int flag = vaild;
int my_atoi(const char *str){
long long ret = 0;
int symbol = 1;
//断言str!=NULL
assert(str);
//判断空字符
if( '\0' == *str ){
flag = invaild;
return 0;
}
//去掉空格、制表符
while(isspace(*str)){
str++;
}
//符号位判断
if('-'==*str){
symbol = -1;
str++;
}else if('+'==*str){
str++;
}else if(((*str<='0')&&(*str>='9'))){
flag = invaild;
return 0;
}
//其他异常情况处理完毕,开始转换
while((*str!='\0')&&(*str>='0')&&(*str<='9')){
ret = (ret*10 + *str-'0');
str++;
}
//带上符号位
ret *= symbol;
//检测溢出
//int 0111 1111 1111 1111 1111 1111 1111 1111 正溢出
// 7 f f f f f f f
// 1000 0000 0000 0000 0000 0000 0000 0000 负溢出
// 8 0 0 0 0 0 0 0
if(((ret>0x7fffffff)&&(1==symbol)) ||
(ret<(signed int)0x80000000)&&(-1==symbol)){
flag = invaild;
return 0;
}
//ret合法
flag = vaild;
return ret;
}
//打印atoi函数状态+\n
void PrintState(){
if(flag){
printf("异常\n");
}else{
printf("正常\n");
}
}
//测试函数
void FunTest(){
printf("value=%d,state=",my_atoi("123456789"));
PrintState();//正常
printf("value=%d,state=",my_atoi("-123456789"));
PrintState();//正常
printf("value=%d,state=",my_atoi("-123456789sassa"));
PrintState();//正常,遇到字母终止
printf("value=%d,state=",my_atoi(" -123456789sassa"));
PrintState();//正常,前面带空格
printf("value=%d,state=",my_atoi(""));
//////////////异常情况/////////
printf("\n\n");
PrintState();//异常:空字符串
printf("value=%d,state=",my_atoi("123456789123456789"),flag);
PrintState();//异常:正溢出
printf("value=%d,state=",my_atoi("-123456789123456789"),flag);
PrintState();//异常:负溢出
printf("value=%d,state=",my_atoi("dasdsa"),flag);
PrintState();//异常:无法转换
}
int main(){
FunTest();
return 0;
}

  彩蛋:在写测试函数时,有一件事,始终不得其解,一开始我将测试代码写成了这样:

void FunTest(){
printf("value=%d,state=%d\n",my_atoi("123456789"),flag);//正常
printf("value=%d,state=%d\n",my_atoi("-123456789"),flag);//正常
printf("value=%d,state=%d\n",my_atoi("-123456789sassa"),flag);//正常,遇到字母终止
printf("value=%d,state=%d\n",my_atoi(" -123456789sassa"),flag);//正常,前面带空格
printf("\n\n\n");
printf("value=%d,state=%d\n",my_atoi(""),flag);//异常:空字符串
printf("value=%d,state=%d\n",my_atoi("123456789123456789"),flag);//异常:正溢出
printf("value=%d,state=%d\n",my_atoi("-123456789123456789"),flag);//异常:负溢出
printf("value=%d,state=%d\n",my_atoi("dasdsa"),flag);//异常:无法转换
}

  测试时,发现一件诡异的事情!!!!!!!

  结果输出是这样:

value=123456789,state=0
value=-123456789,state=0
value=-123456789,state=0
value=-123456789,state=0 value=0,state=0 //卧槽!!!为什么是0?
value=0,state=1
value=0,state=1
value=0,state=1

  我还特意跟进函数体内看,发现全局变量flag确实被改为了1,但为什么输出的是0呢???

  正当我百思不得其解时,突然想到printf函数的调用约定是_cdel!!!!

  因此,_cdel调用约定,是将参数由右向左压栈,因此它先将flag压栈,然后再执行my_atoi函数,在my_atoi函数体内修改了全局变量flag.....

  所以,最终输出了0!

  因此,才有了最终代码!

  

【C语言】模拟实现atoi函数的更多相关文章

  1. C语言::模拟实现strlen函数

    题目要求 编写一个C语言程序模拟实现strlen函数. 算法 strlen函数功能是计算字符串中字符的个数.(除\0外) 而字符串本身就是一个字符数组,只不过末尾以\0结束. 因此,我们只需遍历除\0 ...

  2. 【c语言】 模拟实现库函数的atoi函数

    // 模拟实现库函数的atoi函数 #include <stdio.h> #include <string.h> #include <assert.h> #incl ...

  3. C语言itoa()函数和atoi()函数详解(整数转字符C实现)

    1.int/float to string/array: C语言提供了几个标准库函数,可以将任意类型(整型.长整型.浮点型等)的数字转换为字符串,下面列举了各函数的方法及其说明. ● itoa():将 ...

  4. C语言itoa()函数和atoi()函数详解(整数转字符)

    http://c.biancheng.net/cpp/html/792.html C语言提供了几个标准库函数,可以将任意类型(整型.长整型.浮点型等)的数字转换为字符串. 以下是用itoa()函数将整 ...

  5. C语言itoa函数和atoi 函数

    C语言提供了几个标准库函数,可以将任意类型(整型.长整型.浮点型等)的数字转换为字符串.以下是用itoa()函数将整数转 换为字符串的一个例子: # include <stdio.h>  ...

  6. [置顶] C语言itoa()函数和atoi()函数详解(整数转字符C实现)

    头文件:#include <stdlib.h> atoi() 函数用来将字符串转换成整数(int),其原型为: int atoi (const char * str); [函数说明]ato ...

  7. 【转载】C语言itoa()函数和atoi()函数详解(整数转字符C实现)

    本文转自: C语言itoa()函数和atoi()函数详解(整数转字符C实现) 介绍 C语言提供了几个标准库函数,可以将任意类型(整型.长整型.浮点型等)的数字转换为字符串. int/float to ...

  8. C语言itoa()函数和atoi()函数详解(整数转字符C实现)【转载】

    文章转载自https://www.cnblogs.com/bluestorm/p/3168719.html   C语言提供了几个标准库函数,可以将任意类型(整型.长整型.浮点型等)的数字转换为字符串. ...

  9. C语言atoi函数

    目录 1.包含头文件 2.函数声明 3.功能说明 4.示例 5.其它说明 6.版权声明 C语言提供了一系列函数把字符串转换为整数:atoi.atol.atoll和atoq. 1.包含头文件 #incl ...

随机推荐

  1. DLL 导出变量

    声明为导出变量时,同样有两种方法:   第一种是用__declspec进行导出声明 #ifndef _DLL_SAMPLE_H #define _DLL_SAMPLE_H // 如果定义了C++编译器 ...

  2. 四色GDOI&GDOI2015滚粗记

    好吧自己太弱写不了什么四色NOI只能学学别人写个四色GDOI了...首先自己还是太弱所以就被学校卡了个名额就进不了省队了QAQ.自己GDOI觉得考得不错可是NOIP毕竟少了人家5分根本追不上去好不QA ...

  3. linux下apache,php的安装

    apache的安装 1.下载httpd-2.4.16.tar.gz, apr-1.5.2.tar.gz,apr-util-1.5.4.tar.gz,pcre-8.37.zip,解压 2.注意看apac ...

  4. 从0移植uboot (二) _启动流程分析

    经过了上一篇的配置,我们已经执行make就可以编译出一个uboot.bin,但这还不够,首先,此时的uboot并不符合三星芯片对bootloader的格式要求,其次,此时的uboot.bin也没有结合 ...

  5. 我个人的Java学习经验(一家之言)

    声明:本文只是我的个人经验之谈,或者连经验之谈都算不上,因为我觉得自己还是个新手,没有什么经验可谈,就算是我分享一下自己从开始学习Java到现在的一些心路历程吧,各位看官暂且看吧,欢迎交流.第一部分算 ...

  6. 【转】Docker —— 从入门到实践

    http://yeasy.gitbooks.io/docker_practice/content/index.html Docker 是一个开源项目,诞生于 2013 年初,最初是 dotCloud ...

  7. HttpWebRequest 模拟网站登录获取数据

    此文档仅仅是一个BaseCode,已做后续查阅 项目使用IBM Platform Symphony分布式平台,所有业务处理都在这个分布式平台上计算,需求是获取这些计算机机群的运行状态,和每一个服务的的 ...

  8. eclipse中注释常用关键字

    关键词列表: @author 作者名 @date 日期 @version 版本标识 @parameter 参数及其意义 @since 最早使用该方法/类/接口的JDK版本 @return 返回值 @t ...

  9. 删除bin后,Eclipse重新编译项目

    今天做"用java.util.Properties类读写配置文件"Demo时,在编译项目时由于配置资源文件一起写入bin了.而Demo修改了配置文件,从新运行时配置文件不再更新,于 ...

  10. ArrayList源码剖析

    ArrayList简介 ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存. ArrayList不是线程安全的,只能用在单线程环境下,多线 ...