这是书中开头案例提到的一个例子,乍看之下非常简单,但其实其中有很多需要校验的地方。
/**
* 经典题 string -> int
* 面试案例一 p250
* @author Erinn
*
*/
public class Chapter7_StringToInt {
//0 kVaild 1 kInvalid
static int kVaild = 0;
static int kInvalid = 1;
static int g_nStatus;
public static void main(String args[]){
String s ="12345";
int res = StrToInt(s);
if(g_nStatus == 0)System.out.println("Int is " + res);
}
/**
* 预处理
* 判断是否合法输入
* 以及是否有符号位
*
* @param s
* @return
*/
private static int StrToInt(String s) {
g_nStatus = kInvalid;
long num = 0;
if(s != null && s.length() != 0){
boolean minus = false;
if(s.charAt(0) == '+') s = s.substring(1);
else if(s.charAt(0) == '-') {
s = s.substring(1);
minus = true;
}
if(s.length() != 0) num = StrToIntCore(s, minus);
}
return (int)num;
}
/**
* 核心代码
*
* @param s
* @param minus
* @return
*/
private static long StrToIntCore(String s, boolean minus) {
long num = 0;
while(s.length() != 0){
if(s.charAt(0) >= '0' && s.charAt(0) <= '9'){
int flag = minus ? -1 : 1;
num = num * 10 + flag * (s.charAt(0) - '0');
//0x7FFFFFFF
int max = Integer.MAX_VALUE;
//0x80000000
int min = Integer.MIN_VALUE;
if((!minus && num > 0x7FFFFFFF) || (minus && num < 0x80000000)){
num = 0;
break;
}
s = s.substring(1);
}else{
num = 0;
break;
}
}
if(s.length() == 0) g_nStatus = kVaild;
return num;
}
}
下面我们来简单分析一下代码
首先我们g_nStatus状态位,用来标记输入是否合法。
//0 kVaild 1 kInvalid
static int kVaild = 0;
static int kInvalid = 1;
static int g_nStatus;
接着我们判断是否是合法输入,排除两种非法输入情况,再取得符号位(如果有的话),判断是否只是输入符号,这样也是非法。
/**
* 预处理
* 判断是否合法输入
* 以及是否有符号位
*
* @param s
* @return
*/
private static int StrToInt(String s) {
g_nStatus = kInvalid;
long num = 0;
if(s != null && s.length() != 0){
boolean minus = false;
if(s.charAt(0) == '+') s = s.substring(1);
else if(s.charAt(0) == '-') {
s = s.substring(1);
minus = true;
}
if(s.length() != 0) num = StrToIntCore(s, minus);
}
return (int)num;
}
下面是核心代码,首先要注意的是因为是String转Integer,所以需要考虑可能超过Integer型最大范围。输入如“2@3”,这种非法输入将因为存在非0-9的字符而被判定为非法。注意,前面我们已经处理好首位符号问题。下面我们来看下主体。
while(s.length() != 0){
if(s.charAt(0) >= '0' && s.charAt(0) <= '9'){
int flag = minus ? -1 : 1;
num = num * 10 + flag * (s.charAt(0) - '0');
//0x7FFFFFFF
int max = Integer.MAX_VALUE;
//0x80000000
int min = Integer.MIN_VALUE;
if((!minus && num > 0x7FFFFFFF) || (minus && num < 0x80000000)){
num = 0;
break;
}
s = s.substring(1);
}else{
num = 0;
break;
}
}
接着上文,有了符号位,我们可以得到每位是正还是负,对于将char转成int,简单的方式是字符位值-‘0’。接着判断是否超过了Integer边界,0x7FFFFFFF和0x80000000两个数的意义code中已经做了标记。超过Integer型边界和出现非法字符都会在s.length() != 0的情况下跳出。
if(s.length() == 0) g_nStatus = kVaild;
故上式的情况是善终的情况,将结果置为合法输入,最后返回num结果。