刷题__力扣解题(2019.19.06)

题目:
请你来实现一个 atoi 函数,使其能将字符串转换成整数。

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

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

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

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

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

说明:

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

用了两种解法:

解法一:看起来就比较复杂,没有认真思考仔细审题就是这个结果,费时费力。

int myAtoi(char * str)
{
    int int_max = 2147483647;
    int int_min = -2147483648;
    int num = 0,str_value = 0;
    char plus_minus = 1,time = 0;
	
	/*没有对字符串做模块的划分,整体循环去判断,需要多增加判断的条件。*/
    while( *str != '\0'){
        if(*str == ' '){
            if(num == 0 && time == 0)
                str++;
            else
                break;   
        }else if(*str == '+'){
            if(num == 0 && time == 0){
                plus_minus = 1;
                str++;
                time++;
            }else{
                break;
            }
        }else if(*str == '-'){
            if(num == 0 && time == 0){
                plus_minus = 0;
                str++; 
                time++;
            }else{
                break;
            }
        }else if(*str >= '0' && *str <= '9'){            
            
            str_value = (int)(*str) - 48;
			
			/*采用int类型去判断是否溢出,只能判断7位数(不然会导致溢出),最后第8位要单独拿出来做判断*/
            if(num < int_min/10 || (num == int_min/10 && str_value >= 8)){
                return int_min;
                break;
            }else if(num > int_max/10 || (num == int_max/10 && str_value >= 7)){
                return int_max;
                break;
            }
			
			/*计算值的时候要对正负进行判断,并且要注意num是否为0值*/
            if(plus_minus == 0){
                num = -(num*10 + str_value);
                if(num != 0)
                    plus_minus = 1;
            }else{
                if(num >= 0)
                    num = num*10 + str_value;
                else if(num < 0)
                    num = num*10 - str_value;
            }
            str++;
            time++;
        }else{
            break;
        }
    }

    return num;
}

解法二:模块划分得比较清楚,易读性高。
仔细解读题目就可以知道,在有效字符之前(‘0~9’)只允许空格和‘+’‘-’号出现,且正负符号只能出现在有效数字的前面,也就是说只允许出现“空格”+“正负符号”+“有效字符”的组合,其余不符合条件的情况,返回0.

int myAtoi(char * str)
{
    char plus_minus = 1;
    long int num = 0;

    while(*str == ' '){
        str++;
    }
    
    if(*str == '-'){
        plus_minus = 0;
        str++;
    }else if(*str == '+'){
        str++;
    }

    while(*str != '\0'){
        if(*str >= '0' && *str <= '9'){
            num = (num*10 + (*str-'0')); 
            /*这里采用了long int类型的数据来存放转换后的值,简化了对溢出的判断*/
            if(num > 0x7fffffff) 
                return plus_minus ? 0x7fffffff:0x80000000;
            str++;
        }else{
            break;
        }
    }

    return plus_minus ? num:-num;
}

值得注意的地方:

0x7fffffff 表示正数:2147483647;
0x80000000 表示负数:-2147483648;

学过计算机基础的都知道,计算机中:
正数:原码 = 反码 = 补码;
负数:反码 = 原码取反;补码=反码+1;

按照这样的规律理解0x80000000对应十进制的-0,但是打印出来确是-2147483648;

原因是在十六进制中负数的二进制原码的最高位是符号位,后面的31位为序号位,不是值。序号位算出来的值表示负数中从最小值开始到0的位置数。比如:

int类型的取值范围为[-2 ^31 ~ 2 ^31]

0x800000000
原码 1000 0000 0000 0000 0000 0000 0000 0000
最高位为1,为负数,序号位的值为0;表示负数范围内从左到右第一位,即-2 ^31。

再来看看0xFFFFFFFF
原码 1111 1111 1111 1111 1111 1111 1111 1111
最高位为1 ,为负数,序号位为第(2 ^ 31)-1位 (111 1111 1111 1111 1111 1111 1111 1111=(2 ^ 31-1) 所以0xFFFFFFFF为负数从小到大 第2^31-1位 ,
即-2 ^ 31+2 ^ 31 - 1= -1

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值