这看起来是很简单的题目,实现基本功能 ,大部分人都能用10行以内的代码解决。但是,当咱们要把不少特殊状况即测试用例都考虑进去,却不是件容易的事。解决数值转换问题自己并不难,但我但愿在 写转换数值的代码以前,应聘者至少能把空指针,空字符串”“,正负号,溢出等方方面面的测试用例都考虑到,而且在写代码的时候对这些特殊的输入都定义好合 理的输出。固然,这些输出并不必定要和atoi彻底保持一致,但必需要有显式的说明,和面试官沟通好。java
这个应聘者最大的问题就是尚未养成在写代码以前考虑全部可能的测试用例的习惯,逻辑不够严谨,所以一开始的代码只处理了最基本的数值转换。后来我 每次提醒他一处特殊的测试用例以后,他改一处代码。尽管他已经作了两次修改,但仍然有很多很明显的漏洞,特殊输入空字符串”“,边界条件好比最大的正整数 与最小的负整数等。因为这道题思路自己不难,所以我但愿他把问题考虑得很可能周到,代码尽可能写完整。git
归纳起来有几种状况面试
1)字符串开头是“+”号或“-”号的处理ide
2)非法字符的判断(不是数字)函数
3)整数溢出问题。测试
看看Java函数库中的Integer.parseInt(String sting)的源码如何处理这些问题的。this
/** * Parses the specified string as a signed decimal integer value. The ASCII * character \u002d ('-') is recognized as the minus sign. * * @param string * the string representation of an integer value. * @return the primitive integer value represented by {@code string}. * @throws NumberFormatException * if {@code string} cannot be parsed as an integer value. */ public static int parseInt(String string) throws NumberFormatException { return parseInt(string, 10); } /** * Parses the specified string as a signed integer value using the specified * radix. The ASCII character \u002d ('-') is recognized as the minus sign. * * @param string * the string representation of an integer value. * @param radix * the radix to use when parsing. * @return the primitive integer value represented by {@code string} using * {@code radix}. * @throws NumberFormatException * if {@code string} cannot be parsed as an integer value, * or {@code radix < Character.MIN_RADIX || * radix > Character.MAX_RADIX}. */ public static int parseInt(String string, int radix) throws NumberFormatException { if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) { throw new NumberFormatException("Invalid radix: " + radix); } if (string == null) { throw invalidInt(string); } int length = string.length(), i = 0; if (length == 0) { throw invalidInt(string); } boolean negative = string.charAt(i) == '-'; if (negative && ++i == length) { throw invalidInt(string); } return parse(string, i, radix, negative); } private static int parse(String string, int offset, int radix, boolean negative) throws NumberFormatException { int max = Integer.MIN_VALUE / radix; int result = 0, length = string.length(); while (offset < length) { int digit = Character.digit(string.charAt(offset++), radix); if (digit == -1) { throw invalidInt(string); } if (max > result) { throw invalidInt(string); } int next = result * radix - digit; if (next > result) { throw invalidInt(string); } result = next; } if (!negative) { result = -result; if (result < 0) { throw invalidInt(string); } } return result; }
parseInt(String string, int radix)判断了spa
1) radix进制超出范围 ( Character. MIN_RADIX = 2, Character. MAX_RADIX )=36).net
2)字符串为null指针
3)字符串长度为空
4)字符串第一位为“-”且只有一位
没有异常以后进行 parse(String string, int offset, int radix, boolean negative) 判断,参数即字符串,偏移量,进制, negative (若是开头没有“-”则offset=0,negative=false,不然为offset=1,neagtive=true)
在 parse(String string, int offset, int radix, boolean negative)主要进行了溢出的判断。利用 offset++来控制移动, 在 while (offset < length) 循环中 直到倒数 第二位的时候,若是已经 小于 max = Integer.MIN_VALUE / radix 的话代表必定会溢出。例如"-2147483648"
倒数第二位的时候 :result= -214748364,max = -214748364,max>result不成立代表 能够进行最后一位的处理。
以下代码:
package cglib;
public class jiekou {
public static void main(String[] args) {
// TODO 自动生成的方法存根
try {
System.out.println(parseInt("cao21'''474fefda8364fe7"));
//System.out.println(parseInt(""));
System.out.println(parseInt(null));
System.out.println(parseInt("-2147483648"));
System.out.println(parseInt("-2147483651"));
System.out.println(parseInt("-2147483648"));
System.out.println(parseInt("-21474836410"));
} catch (MyException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
private static int parseInt(String string) throws MyException {
/* 异常状况1:字符串为null */
if (string == null) {
throw new MyException("字符串为null!");
}
int length = string.length(), offset = 0;
/* 异常状况2:字符串长度为0 */
if (length == 0) {
throw new MyException("字符串长度为0!");
}
boolean negative = string.charAt(offset) == '-';
/* 异常状况3:字符串为'-' */
if (negative && ++offset == length) {
throw new MyException("字符串为:'-'!");
}
int result = 0;
char[] temp = string.toCharArray();
while (offset < length) {
char digit = temp[offset++];
if (digit <= '9' && digit >= '0') {
int currentDigit = digit - '0';
/*
* 异常状况4:已经等于Integer.MAX_VALUE / 10,判断要添加的最后一位的状况:
* 若是是负数的话,最后一位最大是8 若是是正数的话最后一位最大是7
*/
if (result == Integer.MAX_VALUE / 10) {
if ((negative == false && currentDigit > 7)
|| (negative && currentDigit > 8)) {
throw new MyException("溢出!");
}
/*
* 异常状况5:已经大于Integer.MAX_VALUE / 10
* 不管最后一位是什么都会超过Integer.MAX_VALUE
*/
} else if (result > Integer.MAX_VALUE / 10) {
throw new MyException("溢出!");
}
int next = result * 10 + currentDigit;
result = next;
}
}
if (negative) {
result = -result;
}
return result;
}
}
/* 自定义异常 */
@SuppressWarnings("serial")
class MyException extends Exception {
/**
*
*/
@SuppressWarnings("unused")
private static long serialVersionUID = 1749149488419303367L;
String message;
public MyException(String message) {
// TODO 自动生成的构造函数存根
this.message = message;
}
@Override
public String getMessage() {
// TODO 自动生成的方法存根
return message;
}
}
输出:
147483647
cglib.MyException: 字符串为null!
at cglib.jiekou.parseInt(jiekou.java:25)
at cglib.jiekou.main(jiekou.java:10)
或者:
package cglib;
public class jiekou {
/**
* 题目:实现一个函数stringToInt,实现把字符串转换成整数这个功能,
* 不能使用atoi或者其余相似的库函数。
*
* @param num
* @return
*/
public static int stringToInt(String num) {
if (num == null || num.length() < 1) {
throw new NumberFormatException(num);
}
char first = num.charAt(0);
if (first == '-') {
return parseString(num, 1, false);
} else if (first == '+') {
return parseString(num, 1, true);
} else if (first <= '9' && first >= '0') {
return parseString(num, 0, true);
} else {
throw new NumberFormatException(num);
}
}
/**
* 判断字符是不是数字
*
* @param c 字符
* @return true是,false否
*/
private static boolean isDigit(char c) {
return c >= '0' && c <= '9';
}
/**
* 对字符串进行解析
*
* @param num 数字串
* @param index 开始解析的索引
* @param positive 是正数仍是负数
* @return 返回结果
*/
private static int parseString(String num, int index, boolean positive) {
if (index >= num.length()) {
throw new NumberFormatException(num);
}
int result;
long tmp = 0;
while (index < num.length() && isDigit(num.charAt(index))) {
tmp = tmp * 10 + num.charAt(index) - '0';
// 保证求的得的值不超出整数的最大绝对值
if (tmp > 0x8000_0000L) {
throw new NumberFormatException(num);
}
index++;
}
if (positive) {
if (tmp >= 0x8000_0000L) {
throw new NumberFormatException(num);
} else {
result = (int) tmp;
}
} else {
if (tmp == 0x8000_0000L) {
result = 0x8000_0000;
} else {
result = (int) -tmp;
}
}
return result;
}
public static void main(String[] args) {
//System.out.println(Integer.parseInt(Integer.MIN_VALUE + ""));
// System.out.println(0x8000_0000L);
// System.out.println(stringToInt(""));
System.out.println(stringToInt("123"));
System.out.println(stringToInt("+123"));
System.out.println(stringToInt("-123"));
System.out.println(stringToInt("aaa"));
System.out.println(stringToInt("+2147483647"));
System.out.println(stringToInt("-2147483647"));
System.out.println(stringToInt("+2147483648"));
System.out.println(stringToInt("-2147483648"));
System.out.println(stringToInt("+2147483649"));
System.out.println(stringToInt("-2147483649"));
System.out.println(stringToInt("+"));
System.out.println(stringToInt("-"));
}
}
输出: Exception in thread "main" java.lang.NumberFormatException: aaa at cglib.jiekou.stringToInt(jiekou.java:24) at cglib.jiekou.main(jiekou.java:80) 123 123 -123