题目描述
将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0
比如+2147483647,就是有效的2147483647。而1a33就是无效的,因为有个a。
这道题对跨行过来的不太友好,需要一些编码的基础知识,就很难受。而且本题的边界需要考虑的比较详细(例如null、空字符串、带有正负号、字符不是数字、溢出等等)。我将按照某个通过测试的代码,分析整个解题思路。
思路:首先什么边界都不考虑,用最简单的来思考,就是字符串123转换成数字123,ASCII码中48~57为0到9十个阿拉伯数字。所以,当字符1要转换成数字1时,需要将字符1转换成ASCII码翻译出的数字再减去48,才是我们要的解。注意,这里可以判断其他字符,如果换算之后的数字不在0到9,就说明是其他字符,就可以结束了。针对这一步骤,应该可以写出如下几行核心代码:
//对于字符串中第i位元素的处理 int a=(int) (chars[i]-'0'); if(a<0 || a>9){//减去48后的数字,必须在0到9之间才有效(其他字符就不行) return 0;
然后就是对于整个串的处理。对于正数,求得的数字应该做加法,如果给出的数是负数,那么在换算过来后,应当做减法。所以可以看到,此时用一个boolean变量来记录正负非常合适。因为字符串的某一个字符对应的可能是一个百位,千位上的数,所以在比较每一个i位置的字符时,都需要进行相应的乘10运算。
//这个minus用来判断正负号 num= (minus==false) ? num*10+a : num*10-a;
既然选择了设置boolean变量,就应该添加对应的判断条件,比如chars[i]=='+',chars[i]=='-'。并在判断过后改写相应的boolean变量。
至此为止,将上述过程合并后,对于我们应该来说,就完成了所有核心的部分,接下来,我们需要考虑边界情况。
字符串为null,字符串长度为0,以及字符串太长,从而超出int型的范围,这几个特殊的边界考虑清楚即可(其他字符和正负号在核心代码部分解决)。字符串为null,字符串长度为0这两种情况在进入循环判断前就应该判断,而溢出就必须在换算过后进行判断。
写法:
public class Solution { public int StrToInt(String str) { if(str == null || str.length()<=0) return 0; char[] chars = str.toCharArray(); long num=0; //先用long来存储,以防止越界。换算出来的数可能整型溢出 boolean minus=false; for(int i=0; i<chars.length; i++){ if(i==0 && chars[i]=='-'){ minus=true; }else if(i==0 && chars[i]=='+'){ minus=false; }else{ int a=(int) (chars[i]-'0'); if(a<0 || a>9){ return 0; } num= (minus==false) ? num*10+a : num*10-a; if((!minus && num>Integer.MAX_VALUE)//Integer.MAX_VALUE 0x7FFFFFFF ||(minus && num<Integer.MIN_VALUE)){//Integer.MIN_VALUE 0x80000000 return 0; } } } return (int)num; } }
小结:应该是把所有的情况都考虑了吧,我编码这部分的知识非常薄弱,如果有没有考虑完整的部分,希望大家能批评指正。