最近看完Linux线程然后在看网络编程,但是网络编程新概念太难了,就看剑指offer这个书缓缓。里面由关一个atoi函数实现的问题感觉非常有趣,就介绍给大家。
#include <stdlib.h>
int atoi(const char *nptr);
atoi() 函数会扫描参数 str 字符串,跳过前面的空白字符(例如空格,tab缩进等,可以通过 isspace() 函数来检测),直到遇上数字或正负符号才开始做转换,而再遇到非数字或字符串结束时(‘\0’)才结束转换,并将结果返回。返回转换后的整型数;如果 str 不能转换成 int 或者 str 为空字符串,那么将返回 0。
下面是四种atoi的实现,代码的注释将对这集中方法进行一一评析
#include<stdio.h>
#include<string.h>
#define bool int
#define false 0
#define true 1
enum Status{kValid=0,kInvalid};
int g_nStatus=kValid;
int StrToInt_1(const char *str)
{
int number=0;
while(*str!=0)
{
number=number*10+*str-'0';
++str;
}
return number;
}
/*
如果让大家来写,估计大部分人都会觉得这么简单,简直so easy,其实不然,加入我们输入的为空字符串,那么在gcc下直接会核心转储
*/
int StrToInt_2(const char *str)
{
if(str==NULL)
return 0;
int number=0;
while(*str!=0)
{
number=number*10+*str-'0';
++str;
}
return number;
}
/*
这个算是对StrToInt_1的一个优化吧,处理了如果为空字符串的情况
但是,假如恰巧函数的参数为0",那么究竟是我们输入的字符串为空串呢,还是字符串为空呢,我们无法根据函数的返回值去判断参数是否符合要求。同时,该函数还未考虑到字符串中的正负号问题。
*/
int StrToInt_3(const char *str)
{
g_nStatus=kInvalid;
int num=0;
if(str!=NULL)
{
const char* digit=str;
bool minus=false;
if(*digit=='+')
digit++;
else if(*digit=='-')
{
digit++;
minus=true;
}
while(*digit!='\0')
{
if(*digit>='0'&&*digit<='9')
{
num=num*10+(*digit-'0');
digit++;
}
else
{
num=0;
break;
}
}
if(*digit=='\0')
{
g_nStatus=kValid;
if(minus)
num=0-num;
}
}
return num;
}
/*
该函数优化了StrToInt_2,加入了全局变量,若输入字符串为非法输入则全局变量g_nStatus为kInvalid,同时函数结束。并且加入了处理正负号的步骤但是没有考虑到数据溢出的问题,同时还未考虑到字符串为"","+","-"的这些情况。
*/
long long StrToIntCore(const char* digit,bool minus)
{
long long num=0;
while(*digit!='\0')
{
if(*digit>='\0'&&*digit<='9')
{
int flag=minus?-1:1;
num=num*10+flag*(*digit-'0');
if(!minus&&num>0x7fffffff||(minus&&num<0x80000000))
{
num=0;
break;
}
digit++;
}
else
{
num=0;
break;
}
}
if(*digit=='\0')
g_nStatus=kValid;
return num;
}
int StrToInt_4(const char *str)
{
g_nStatus=kInvalid;
long long num=0;
if(str!=NULL&&*str!='\0')
{
bool minus=false;
if(*str=='+')
str++;
else if(*str=='-')
{
str++;
minus=true;
}
if(*str!='\0')
num=StrToIntCore(str,minus);
}
return num;
}
/*
这个就属于终极版了,首先考虑到了空串,"","+","-"的问题,同时还处理了溢出的问题
*/