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函数的更多相关文章
-
C语言::模拟实现strlen函数
题目要求 编写一个C语言程序模拟实现strlen函数. 算法 strlen函数功能是计算字符串中字符的个数.(除\0外) 而字符串本身就是一个字符数组,只不过末尾以\0结束. 因此,我们只需遍历除\0 ...
-
【c语言】 模拟实现库函数的atoi函数
// 模拟实现库函数的atoi函数 #include <stdio.h> #include <string.h> #include <assert.h> #incl ...
-
C语言itoa()函数和atoi()函数详解(整数转字符C实现)
1.int/float to string/array: C语言提供了几个标准库函数,可以将任意类型(整型.长整型.浮点型等)的数字转换为字符串,下面列举了各函数的方法及其说明. ● itoa():将 ...
-
C语言itoa()函数和atoi()函数详解(整数转字符)
http://c.biancheng.net/cpp/html/792.html C语言提供了几个标准库函数,可以将任意类型(整型.长整型.浮点型等)的数字转换为字符串. 以下是用itoa()函数将整 ...
-
C语言itoa函数和atoi 函数
C语言提供了几个标准库函数,可以将任意类型(整型.长整型.浮点型等)的数字转换为字符串.以下是用itoa()函数将整数转 换为字符串的一个例子: # include <stdio.h> ...
-
[置顶]
 C语言itoa()函数和atoi()函数详解(整数转字符C实现)
头文件:#include <stdlib.h> atoi() 函数用来将字符串转换成整数(int),其原型为: int atoi (const char * str); [函数说明]ato ...
-
【转载】C语言itoa()函数和atoi()函数详解(整数转字符C实现)
本文转自: C语言itoa()函数和atoi()函数详解(整数转字符C实现) 介绍 C语言提供了几个标准库函数,可以将任意类型(整型.长整型.浮点型等)的数字转换为字符串. int/float to ...
-
C语言itoa()函数和atoi()函数详解(整数转字符C实现)【转载】
文章转载自https://www.cnblogs.com/bluestorm/p/3168719.html C语言提供了几个标准库函数,可以将任意类型(整型.长整型.浮点型等)的数字转换为字符串. ...
-
C语言atoi函数
目录 1.包含头文件 2.函数声明 3.功能说明 4.示例 5.其它说明 6.版权声明 C语言提供了一系列函数把字符串转换为整数:atoi.atol.atoll和atoq. 1.包含头文件 #incl ...
随机推荐
-
[Leetcode] Number of Digit Ones
Given an integer n, count the total number of digit 1 appearing in all non-negative integers less th ...
-
Uploadify使用随笔
最近项目使用了Uploadify一个上传插件,感觉的挺好用的. 上传控件: 引用JS <script src='<% =ResolveUrl("~/JS/Uploadify/jq ...
-
SVN修改用户名与密码
由于在svn的界面中并没有为我们提供直接更换用户名密码的地方,所以一旦我们需要更换用户名的就需要自己想一些办法. 解决方案如下: 在Eclipse使用SVN的过程中大多数人往往习惯把访问SVN的用户名 ...
-
Android Broadcast 和 iOS Notification
感觉以上2个机能有许多相似之处,作个记录,待研究!
-
html5,新增的元素,fieldset legend
<form action=""> <fieldset> <legend>用户注册</legend> ...
-
Repair the database using DBCC CHECKDB
So now if you want to place AdventureWorks2008R2 sample database in a single-user mode, then write t ...
-
dreamweaver cs5中提示扩展管理不可用
下载: Extension Manager CS5.5 for Windows 安装后重启就能用了
-
编译器错误消息: CS0016: 未能写入输出文件
“/”应用程序中的服务器错误. 编译错误 说明: 在编译向该请求提供服务所需资源的过程中出现错误.请检查下列特定错误详细信息并适当地修改源代码. 编译器错误消息: CS0016: 未能写入输出文件“c ...
-
Linux学习笔记(7)-系统资源查看
监控系统资源:vmstat #vmstat [采样时间] [ 采样次数] 如:#vmstat 3 2 每3秒采样一次,总共采样2次 输出信息各字段解释 r 表示运行队列,如果运行队列多大表示CPU很繁 ...
-
Oracle建表实例
建表一般来说是个挺简单的事情,但是Oracle的建表语句有很多可选的参数,有些我们可能平时不太用,用的时候又不知道怎么用,这里就写一个较完整的建表的例子: CREATE TABLE banping ...