问题描述:
实现一个int My_atoi(const char* buff),将buff中的数值字符串转换为数值,并且该函数支持十六进制与八进制
例如:char *buff = " 0xff.14",返回255,char *buff = " afda0123"返回83.
分析:
这个题字面意思看起来很简单,就是将字符串中的数值字符串转换为数值并将其返回,但是这个题中有许多的细节都容易被忽略掉:
1.在开始转换之前遇到非所需转换字符时跳过该字符,在开始转换时遇到非所需转换字符就停止转换
2.0x与0X都是十六进制的提示符
3.要考虑到’+’’-‘出现在字符串中的情况,如果在转换前遇到’-'要返回一个负数
4.要分析到int整型溢出的情况!!这一点尤为重要,例如char *str = “316431642664326423”,返回INT_MAX:2147483647,char *str = “-3153642642642354”,返回INT_MIN:- 2147483648
5.在十六进制中字符的大小写差异
6.在8进制转换过程中数字大于等于8了就要停止转换
代码:
//十进制转换
long long dec_atoi(const char*str,bool tag)
{
long long sum = 0;//!!!!sum值不能是int类型,因为在判断是否大于INT_MAX时如果sum是整型,sum*10如果超出了整型就起不到判断的作用
int i = 0;
while(str[i] != '\0' && isdigit(str[i])) //遇到'/0'或者非字符时停止
{
char x = str[i]-'0';
if(tag == false)
{
if( x-1 <= INT_MAX-(sum*10))//注意边界问题
{
sum = sum*10+x;
}
else
{
return INT_MIN;
}
}
else
{
if(x <= INT_MAX-(sum*10))
{
sum = sum*10+str[i] - '0';
}
else
{
return INT_MAX;
}
}
i++;
}
if(tag == false)
{
return sum*-1;
}
return sum;
}
//八进制转换
long long oct_atoi(const char *str,bool tag)
{
long long sum = 0;
int i = 0;
while(str[i] != '\0' && isdigit(str[i]) && isdigit(str[i]) < 8)//遇到大于等于8的数字时停止转换
{
char x = str[i];
if(tag == false)
{
if(x-1 <= INT_MAX - sum*8)
{
sum = sum*8+str[i] - '0';
}
else return INT_MIN;
}
else
{
if(x <= INT_MAX- sum*8)
{
sum = sum*8+str[i] - '0';
}
else return INT_MAX;
}
i++;
}
if(tag == false)
{
return sum*-1;
}
return sum;
}
//十六进制
long long hex_atoi(const char*str,bool tag)
{
long long sum = 0;
int i = 0;
while(str[i] != '\0' && isdigit(str[i]) || isalnum(str[i]))
{
char x = str[i] - '0';
if(isdigit(str[i]))//如果是数字
{
if(tag == 0)
{
if(x-1 <= INT_MAX-sum*16)
{
sum = sum*16+str[i] - '0';
}
else return INT_MIN;
}
else
{
if(x <= INT_MAX - sum*16)
{
sum = sum*16+str[i] - '0';
}
else return INT_MAX;
}
}
else if(isalnum(str[i]))//如果是字母
{
char x = str[i];
x = tolower(x);//将字母转换成小写
if(tag == 0)
{
if(x-1 <= INT_MAX-sum*16)
{
sum = sum*16+(x-'a'+10) - '0';
}
else return INT_MIN;
}
else
{
if(x <= INT_MAX-sum*16)
{
sum = sum*16 + (x-'a'+10);
}
else return INT_MAX;
}
}
i++;
}
if(tag == false)
{
return sum*-1;
}
return sum;
}
//my_aoti函数
int my_atoi(const char *str)
{
if(str == NULL) return -1;
int num = 0;
bool flag = true;
while(*str == ' ') str++;
while(*str != '\0')
{
if(*str == '-')
{
flag = false;
}
if(*str == '+')
{
flag = true;
}
if(*str == '0')
{
if(*(str+1) == 'x' || *(str+1) == 'X')//十六进制
{
num = hex_atoi(str+2,flag);
break;
}
else
{
num = oct_atoi(str+1,flag);
break;
}
}
if(isdigit(*str))
{
num = dec_atoi(str,flag);
break;
}
str++;
}
return num;
}
注意事项:
注意函数的模块化,不要把所有函数写到一个函数里—不好看而且看起来不方便!!,我们要灵活的将一部分功能写到一个函数里,另一部分功能写到另一个函数中,然后进行调用。
在这个函数中我们判断整型溢出时,一定要将sum设置成大于int字节数的类型,因为如果sum是int类型,判断条件(x <= INT_MAX - sum10)中的sum10如果大于了INT_MAX,sum10返回的值就不是我们所需要的值,如果sum是long long类型,sum10得到的就是我们所需要的数用来与INT_MAX进行比较