字符串转数字atoi

常见的面试笔试题
2021-05-17 14:29 · 阅读时长6分钟
小课

atoi是c/c++的库函数,用于将字符串类型转为int类型,这是一个经常出现在面试中的问题,我觉得这道题可简单也可复杂,关键看面试官的发挥。

先看一个最简单的实现,这个实现应该要快速能够写出来,因为这是最基本的实现,这通常也不会是面试官期望的最终答案。

1public class Main {
2
3    public static int atoi(String str) {
4        int result = 0;
5        for (int i = 0; i < str.length(); i++) {
6            result = result * 10 + (str.charAt(i) - '0');
7        }
8        return result;
9    }
10
11    public static void main(String[] args) {
12        System.out.println(atoi("0"));
13        System.out.println(atoi("10"));
14        System.out.println(atoi("123"));
15    }
16}
注意: 这个Java运行环境不支持自定义包名,并且public class name必须是Main

很容易看出来,上面的实现有很多问题,首先是没有处理异常情况,比如说字符串是null,或者包含非数字字符,不支持负数等等,下面再写一个能够支持负数,并且有异常处理的逻辑的实现。

1public class Main {
2
3    public static int atoi(String str) {
4        if (str == null || str.isEmpty()) {
5            throw new NumberFormatException("The str is null or empty.");
6        }
7        char firstChar = str.charAt(0);
8        boolean negative = false;
9        int i = 0;
10        if (firstChar == '-') {
11            negative = true;
12            i++;
13        }
14        int result = 0;
15        for (; i < str.length(); i++) {
16            char ch = str.charAt(i);
17            int value = ch - '0';
18            if (value < 0 || value > 9) {
19                throw new NumberFormatException("The str '" + str + "' contains invalid character.");
20            }
21            result = result * 10 + value;
22        }
23        return negative ? -result : result;
24    }
25
26    public static void main(String[] args) {
27        System.out.println(atoi("0"));
28        System.out.println(atoi("-10"));
29        System.out.println(atoi("123"));
30        System.out.println(atoi("-1 23"));
31    }
32}
33
注意: 这个Java运行环境不支持自定义包名,并且public class name必须是Main

现在看起来好多了,但是还有一个问题没有处理,那就是溢出,整型是有范围的,如果传入的字符串转为数字会超过整型的范围,我们应该抛出异常,而不是返回错误结果。这里有两个小技巧,一是我们需要在溢出的前一次进位的时候判断是否可能溢出,二是为了统一处理正数和负数的情况,在计算过程中我们会统一使用负数,因为使用-Integer.MIN_VALUE作为判断的时候会溢出,如果是正负数分开处理就不用考虑这个问题了。

1public class Main {
2
3    public static int atoi(String str) {
4        if (str == null || str.isEmpty()) {
5            throw new NumberFormatException("The str is null or empty.");
6        }
7        char firstChar = str.charAt(0);
8        int limit = -Integer.MAX_VALUE;
9        boolean negative = false;
10        int i = 0;
11        if (firstChar == '-') {
12            negative = true;
13            limit = Integer.MIN_VALUE;
14            i++;
15        }
16        int min = limit / 10;//在进位前判断,所以除以10,相对于退1位
17        int result = 0;
18        for (; i < str.length(); i++) {
19            char ch = str.charAt(i);
20            int value = ch - '0';
21            if (value < 0 || value > 9) {
22                throw new NumberFormatException("The str '" + str + "' contains invalid character.");
23            }
24            //进位前判断是否溢出
25            if (result < min) {
26                throw new NumberFormatException("The transformed number may overflow");
27            }
28            result *= 10;
29            //拼尾数前判断是否溢出
30            if (result < limit + value) {
31                throw new NumberFormatException("The transformed number may overflow");
32            }
33            result -= value;
34        }
35        return negative ? result : -result;
36    }
37
38    public static void main(String[] args) {
39        System.out.println(atoi(String.valueOf(Integer.MIN_VALUE)));
40        System.out.println(atoi(String.valueOf(Integer.MAX_VALUE)));
41    }
42}
注意: 这个Java运行环境不支持自定义包名,并且public class name必须是Main

标题

标题

https://zhixing.co

atoi笔试题高频面试