剑指 Offer 67. 把字符串转换成整数

写一个函数 StrToInt,实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。

首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。

当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。

该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。

注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。

在任何情况下,若函数不能进行有效的转换时,请返回 0。

说明:

假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,请返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。
在这里插入图片描述在这里插入图片描述

题解

题解转载自Krshets在这里插入图片描述
在这里插入图片描述

class Solution {
    public int strToInt(String str) {
        char[] c = str.trim().toCharArray();
        if(c.length==0) return 0;
        //为什么boundry的值是这个????
        int res=0,boundry = Integer.MAX_VALUE/10;
        //i是c遍历的起始位置
        int i=1,sign=1;
        if(c[0] == '-') sign = -1;
        //第一位不为符号位,则从第一位开始遍历
        else if(c[0] != '+') i = 0;
        for(int j = i; j < c.length; j++){
            //c[j]不为字母,则循环终止
            if(c[j] < '0' || c[j] > '9') break;
            //**** 
            if(res > boundry || res == boundry && c[j] > '7'){
                return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
            }
            res = res * 10 + (c[j] - '0');
        }
        return sign * res;
    }
}

转载自AmadeusMo

Q1:为什么不能直接向int变量赋值-2147483648?

关于代码中对于越界的判断的一个小细节说一点我的理解 简单来说就是如果直接向int变量赋值-2147483648系统会报错,虽然理论上确实可以取到,但是直接赋值不行,下面是详细讨论。

if(res > bndry || res == bndry && str.charAt(j) > ‘7’)
即INT_MIN明明是-2147483648,但是为什么却只需要判断当前字符是否大于7,因为按常理来说当符号为负时str.charAt(j)为’8’也是不越界的,但是为什么这里只判断‘7’呢? 这是因为我们如果直接向一个int变量赋值-2147483648,系统是会报错的(至少在C++中是这样),我们如果想要返回这个数那就需要使用INT_MIN,因为INT_MIN=-2147483648。 那么我们回过头来看这题,考虑字符串为“-2147483648”这种情况,即res==214748364的前提下,当前字符是‘8’,那么按照最常规的思路,这个数是在int的取值范围中,那么我要存放它,但是int变量并不能直接存放这个数,因此我要找一个与-2147483648相等的,可以表示它的数,那就是INT_MIN。因此即使符号是负号,我们仍然可以将判断条件写为 str.charAt(j) > ‘7’ ,因为当取‘8’时我们返回的也是INT_MIN。

关于为什么不能直接向int变量赋值-2147483648,我搜索了一些资料,大致意思是说-2147483648是一个常量表达式而非常量,系统会把它分成两部分,即负号 - 和 数字 2147483648,因此会出现越界的情况。

当然啦,即使int变量能存放下-2147483648,我们依然可以这么写 str.charAt(j) > ‘7’ ,只是这么些会有一点违反我们的直觉,需要思考一下过程才能理解,因此在这里分享一点我的看法,希望能帮助到有同样疑惑的朋友。

Q2:Int的取值范围

转载自AAS48
首先这是针对int占4个字节的情况。
最高位是符号位,1表示是负数,0表示是非负数。
0111 1111 1111 1111,这是int_max,可能我们就会想为什么最小值不是-int_max呢?
因为计算机是以补码的形式来存储数字的,不管-0还是+0,补码都是0000 0000 0000 0000,
这就造成了没有任何一个数的补码是1000 0000 0000 0000,所以就可以把这个补码用来存储一个数(不要浪费资源嘛),就规定用它来存储-(int_max+1),所以int最小值是-2147483648,即 1000 0000 0000 0000。

【拓展】:

因此我们也发现,2147483647 + 1会溢出变成-2147483648
因为2147483647 补码是:0111 1111 1111 1111 1111 1111 1111 1111
加1之后补码就变成了:1000 0000 0000 0000 0000 0000 0000 0000
这正好就是-2147483648的补码

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值