题目:将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0
输入描述:输入一个字符串,包括数字字母符号,可以为空
输出描述:如果是合法的数值表达则返回该数字,否则返回0
输入例子:+2147483647 1a33 输出例子: 2147483647 0
思路:给定一个字符串,要求将这个字符串转换为正数,转换的基本思想很简单,首先将其转换为数组,遍历字符元素,对于每个字符,将其转换为对应的值,例如‘3’转换为3,转换方法很简单,由于字符char对应唯一的一个ascii码,而ascii码是整数,因此可以将其转化(常识:ascii码中0~9分别对应48~57,因此将char-48就转换为char字面的数值,如果不记得0对应48,那么可以直接用char参与运算char-‘0’得到的就是char的字面数值,此外a对应97,A对应65),在遍历时每次在前一个数值的基础上res*10+(char-‘0’)就得到当前的值。
本题的关键考察点是各种特殊情况的全面考虑,保证考虑周全。在优秀情况不明确时需要与面试官进行沟通。
①空输入:str==null或者str.length()<=0;此时直接返回0
在实际中,很多情况下非法输入要求也返回0,而如果正常输入的值是0,那么其返回值也应该是0,这是返回到底是因为值是0还是非法输入呢?这需要区分,在实际中使用一个全局变量valid来作为标记,如果是非法输入,那么返回0同时将valid设置为false;如果是正常的值0那么返回0而valid保持true,于是最终根据valid的值可以判断究竟是正常输入还是非法输入。本题中由于要求非法输入返回0所以直接返回0就可以了。
②输入的字符串含有非数字的字符,例如123a45,于是在遍历时,对于每一个字符要判断其是否在’0’~’9’(或者48~57)范围之内,如果不在就说明输入不合法直接返回0;
③输入的字符串带有符号,例如+123或者-123;于是在遍历之前先专门对第一个字符进行array[0]进行判断,看其是否是‘+’或者‘-’或者没有符号,这决定了最后的结果是否要乘以一个-1,以及如果有符号,则遍历相乘从index=1开始,如果没有符号则遍历相乘从index=0开始。
④输入的字符串只有一个符号例如‘+’或者‘-’
由于对于第一个字符array[0]单独考察,之后遍历的循环范围是i=1;i<length;i++显然不满足值为0,已经包含在上面的结果情况中了。
⑤字符串越界溢出的问题
如果字符串过长,例如str=”12345678987654321”,那么显然是溢出的,因此在遍历数组逐步相乘的过程中就应该每一步都检查一下当前result是否已经溢出,如果溢出则返回0表示不合法输入,并且最好能够抛出一个显示的异常。throw new RuntimeException("上溢出");
并且注意如果定义result为int,而以Integer.MAX_VALUE和Integer.MIN_VALUE作为溢出的比较值的话是错误的,因为某一时刻result在运算赋值时会突然溢出,因此如果设定字符串的转化范围是int,那么result应该使用long,这样才能防止溢出。
注意几点①:Java中==表示比较两个对象的地址是否相同,但是只有对于对象,==才是比较两个对象是否相同,对于基本类型,==依然是比较值是否相同,于是对于String,==是比较两个字符串的地址是否相同,同样值为”abc”的字符串,对象不同他们==为false,但是int,char是基本数据类型,==比较的是他们的值是否相同,因此这里可以使用==比较char是否相同。Char没有equals()方法。②对于整数int,long都是有范围的,他的范围可以自己记住是-2^(8*4-1)~2^(8*4-1)-1即为-2^31~2^31-1或者直接调用方法Integer.MAX_VALUE和Integer.MIN_VALUE来求出范围。③异常抛出之后方法自动结束返回,之后的代码不会再执行,因此在throw异常都为后面的return语句不会得到执行,是编译错误。即异常抛出后程序方法终止,但是try/catch后如果异常捕获则程序继续,这就是try/catch的意义。
//将一个字符串转化为正数int输出,考察的是对特殊情况、边界情况的考虑全面性
publicclass Solution {
public int StrToInt(String str) {
//特殊输入
if(str==null||str.length()<=0)return 0;
//将字符串转化为数组
char[] array=str.toCharArray();
//根据有无+-符号来决定计算值时的起始元素位置
int numberIndex=0;
//表示当前的转换结果,注意,为了避免溢出要使用更高一级的类型
long result=0;
//①常识:字符char不能使用equals方法,char是基本数据类型,与String不同,它的==也是用来比较值
if('+'==array[0]){
numberIndex=1;
}else if('-'==array[0]){
numberIndex=1;
}else{
//说明没有+-号,则从0开始计算数值
numberIndex=0;
}
//遍历非符号的字符,进行结果统计
for(inti=numberIndex;i<array.length;i++){
//判断字符是否是数字
if(array[i]>='0'&&array[i]<='9'){
result=result*10+(array[i]-'0');
//②判断当前结果是否溢出了int的范围,向上溢出必然是正数,于是array[0]=’+’
if(array[0]=='+'&&result>Integer.MAX_VALUE){
//向上溢出
//throw newRuntimeException("向上溢出");
//③抛出异常自动终止程序,可以不返回
return 0;
//向上溢出必然是负数,于是array[0]=’-’
}elseif(array[0]=='-'&&result<Integer.MIN_VALUE){
//向下溢出
//throw newRuntimeException("向下溢出");
return 0;
}
}else{
return 0;
}
}
if(array[0]=='-'){
//由于result是long类型,返回值是int类型,因此在返回时需要强转为int
return (int)(result*(-1));
}else{
return (int)result;
}
}
}