剑指offer 把字符串转换成整数

题目:

将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0

输入描述:

输入一个字符串,包括数字字母符号,可以为空

示例1

输入:+2147483647,  1a33  输出:2147483647,  0

 1 class Solution {
 2 public:
 3     int StrToInt(string str) {
 4         int length = str.length();
 5         int isNegtive = 1, i = 0;
 6         int num = 0;
 7         if( str[i] == '+' || str[i] == '-') {
 8             if( str[i] == '-' ) isNegtive = -1;
 9             i ++;
10         }
11         for(; i < length; i ++){
12             int OverValue;
13             int digit = str[i] - '0';
14             OverValue = num*isNegtive - INT_MAX/10
15                 +(((isNegtive + 1)/2 + digit > 8)? 1 : 0);
16             if(str[i] > '9' || str[i] < '0') return 0;
17             else if(OverValue > 0) return 0;
18             num = digit*isNegtive + num*10;
19         }
20         return num;
21     }
22 };

我的笔记:

  本题主要注意防止数值溢出的问题,

一、关于数值越界:合理利用 INT_MAX/10

  数值越界,即大于 2147483647,或小于 -2147483648。通过观察程序结构,我们发现,每次循环时 num 的值都会扩大10倍(乘以10),那么,我们是否就可以利用 INT_MAX/10 的值来提前一步判断是否会越界呢?这里我们以正数的越界为例进行解释:

  • 当 num > INT_MAX/10 时,说明本轮扩大10倍后,num 必将越界(超过 INT_MAX);
  • 当 num == INT_MAX/10 时,说明扩大10倍后,num 可能越界,也可能不越界,需要利用当前的加数 digit 来进行进一步的判断:当 digit > 7 时(以正数为例),越界;
  • 否则,当 num < INT_MAX/10 时,本轮循环必不越界(扩大10倍后也小于 INT_MAX);

二、将正数、复数的越界判断合并起来

  为了保证代码简洁高效,这里我们不得不寻求一种方法,使正数、负数的越界判断可以合并起来进行(同样,这里我们也利用了数值化的正负标记位 isNegtive):
我们设置一个变量 OverValue 来表示当前的值和 INT_MAX/10 的差,因为 INT_MAX/10 为正数,所以当当前值为负数时,需要统一转化为正数,故而有:

1 OverValue = isNegtive*num - INT_MAX/10;

  这样,当 OverValue > 0 时,越界,OverValue < 0 时,不越界,而当 OverValue == 0 时:
正数时(isNegtive == 1),digit > 7 越界,负数时(isNegtive == -1),digit > 8 越界,通过 (isNegtive+1)/2 来将 -1、1转换为0、1,从而使有关 digit 的判断统一转化为:

  • 当 (isNegtive+1)/2 + digit > 8 时,数值越界;

综上,令:

1 OverValue = isNegtive*num - INT_MAX/10
2           + (((isNegtive+1)/2 + digit > 8) ? 1:0);

则当 overValue > 0 时,数值将会越界,反之,则不会。

参考材料:https://blog.nowcoder.net/n/eb66593eb79a4428a72e385adcfce6dd?f=comment

原文地址:https://www.cnblogs.com/john1015/p/13111004.html