本系列導(dǎo)航:劍指offer(第二版)java實(shí)現(xiàn)導(dǎo)航帖
面試題67:把字符串轉(zhuǎn)換成整數(shù)
題目要求:
如題。
解題思路:
此題比較麻煩的點(diǎn)是特殊情況較多,需要考慮完全稻艰。
1.如果字符串前后有空格拆魏,要去除;
2.如果是空串或null雪猪,要特殊處理栏尚;
3.如果頭部有多個正負(fù)號,要特殊處理只恨;
4.如果數(shù)值超出int的范圍译仗,要特殊處理;比int的最大值還要大官觅,已經(jīng)上溢纵菌,這肯定不能通過數(shù)字的大小比較,所以需要在字符串的狀態(tài)下判斷是否上溢或下溢休涤。
5.遇到非數(shù)字的字符咱圆,則轉(zhuǎn)換停止;
剛剛發(fā)現(xiàn)一個新的情況未做處理功氨,在數(shù)字之前有多個0,如果0之后的數(shù)字有溢出情況序苏,而前面的0又沒有去處,這種溢出就不會被捕獲捷凄,還缺這個情況的判斷忱详。這種思路真心不好,一條主線是轉(zhuǎn)換成整數(shù)跺涤,中間穿插出很多特殊情況的分支匈睁,感覺就像在打補(bǔ)丁。
package chapter7;
/**
* Created with IntelliJ IDEA
* Author: ryder
* Date : 2017/8/22
* Time : 16:06
* Description:把字符串轉(zhuǎn)換成整數(shù)
**/
public class P318_StringToInt {
// atoi的需求是這樣的:
// 如果前面有空格桶错,需要剔除空格航唆;
// 剔除空格后,第一個字符串如果是+號院刁,認(rèn)為是正數(shù)糯钙;如果是-號,認(rèn)為是負(fù)數(shù)黎比;
// 后面的字符如果不是數(shù)字超营,那么返回0,如果是數(shù)字阅虫,返回實(shí)際的數(shù)字演闭。遇到不是數(shù)字的字符,轉(zhuǎn)換結(jié)束颓帝。
// 此外米碰,要考慮空串問題窝革,數(shù)值溢出問題[2^(-31) ~ 2^31-1]。
public static int strToInt(String str) throws Exception{
if(str==null || str.length()==0)
throw new Exception("待轉(zhuǎn)換字符串為null或空串");
String MAX_INT_PLUS_1 = Integer.toString(Integer.MIN_VALUE).substring(1);
StringBuilder stringBuilder = new StringBuilder(str.trim());
int flag = 0; //記錄無符號的正(2)正(1)吕座,負(fù)(-1),初始值(0)
if(stringBuilder.charAt(0)=='-')
flag = -1;
else if(stringBuilder.charAt(0)=='+')
flag = 1;
else if(stringBuilder.charAt(0)>='0'&&stringBuilder.charAt(0)<='9')
flag = 2;
else
return 0;
int endIndex = 1;
while (endIndex<stringBuilder.length()&&stringBuilder.charAt(endIndex)>='0'&&stringBuilder.charAt(endIndex)<='9')
endIndex++;
if(flag==2){
if(stringBuilder.substring(0,endIndex).toString().compareTo(MAX_INT_PLUS_1)>=0)
throw new Exception("數(shù)值上溢,待轉(zhuǎn)換字符串為"+str);
return Integer.parseInt(stringBuilder.substring(0,endIndex));
}
else{
if(flag==1&&stringBuilder.substring(1,endIndex).compareTo(MAX_INT_PLUS_1)>=0)
throw new Exception("數(shù)值上溢,待轉(zhuǎn)換字符串為"+str);
if(flag==-1&&stringBuilder.substring(1,endIndex).compareTo(MAX_INT_PLUS_1)>0)
throw new Exception("數(shù)值下溢,待轉(zhuǎn)換字符串為"+str);
if(flag==-1&&stringBuilder.substring(1,endIndex).compareTo(MAX_INT_PLUS_1)==0)
//此處注意虐译,此種情況不能用絕對值*(-1),該絕對值已經(jīng)超出正數(shù)的最大值
return Integer.MIN_VALUE;
return flag*Integer.parseInt(stringBuilder.substring(1,endIndex));
}
}
public static void funcTest(){
try {
System.out.println(strToInt(" 100")); //100
System.out.println(strToInt("-100")); //-100
System.out.println(strToInt("0")); //0
System.out.println(strToInt("-0"));//0
System.out.println(strToInt("1.23")); //1
System.out.println(strToInt("-1.23")); //-1
System.out.println(strToInt(".123")); //0
}
catch (Exception e){
e.printStackTrace();
}
}
public static void edgeTest(){
try {
System.out.println(strToInt("2147483647")); //2147483647
}
catch (Exception e){
System.out.println(e.getMessage());
}
try {
System.out.println(strToInt("-2147483647")); //-2147483647
}
catch (Exception e){
System.out.println(e.getMessage());
}
try {
System.out.println(strToInt("2147483647")); //2147483647
}
catch (Exception e){
System.out.println(e.getMessage());
}
try {
System.out.println(strToInt("2147483648")); //上溢
}
catch (Exception e){
System.out.println(e.getMessage());
}
try {
System.out.println(strToInt("-2147483648")); //-2147483648
}
catch (Exception e){
System.out.println(e.getMessage());
}
try {
System.out.println(strToInt("-2147483649")); //下溢
}
catch (Exception e){
System.out.println(e.getMessage());
}
try {
System.out.println(strToInt(null)); //待轉(zhuǎn)換字符串為null或空串
}
catch (Exception e){
System.out.println(e.getMessage());
}
try {
System.out.println(strToInt("")); //待轉(zhuǎn)換字符串為null或空串
}
catch (Exception e){
System.out.println(e.getMessage());
}
}
public static void main(String[] args){
funcTest();
edgeTest();
}
}
運(yùn)行結(jié)果
100
-100
0
0
1
-1
0
2147483647
-2147483647
2147483647
數(shù)值上溢,待轉(zhuǎn)換字符串為2147483648
-2147483648
數(shù)值下溢,待轉(zhuǎn)換字符串為-2147483649
待轉(zhuǎn)換字符串為null或空串
待轉(zhuǎn)換字符串為null或空串