题目的边界条件处理

本题的基本思路不难,但对于几个取值特殊的用例进行合理的处理花费了一定的时间。以下为最终实现的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class Solution {
public:
int char2int(char c){
return c-'0';
}

int myAtoi(string s) {
int p=0;
bool negative=false;
bool prezero=false;
bool overflow=false;
//去除空格
while(p<s.length()&&s[p]==' ') p++;

//去除前导零

while(p<s.length()&&s[p]=='0'){
p++;
prezero=true;
}

if(prezero&&(p>=s.length()||s[p]<'0'||s[p]>'9')) return 0;

//判断是否存在负号
if(p<s.length()&&s[p]=='-'){
p++;
negative=true;
}else{
negative=false;
if(s[p]=='+') p++;
}

int sum=0;
while(p<s.length()&&s[p]>='0'&&s[p]<='9'){
if(sum>INT_MAX/10||sum>(INT_MAX-char2int(s[p]))/10){
sum=INT_MAX;
overflow=true;
break;
}
sum=sum*10;

sum=(sum+char2int(s[p]));
p++;
}
if(negative&&overflow) sum=INT_MIN;
else if(negative) sum=(-sum);
return sum;
}
};

在调试过程中,出现了多个特殊取值上处理有误导致的报错,这些数值包括以下情况:

  • “-91283472332”(小于INT_MIN)

  • “00000-42a1234”(前导零就是数值的有效位)

  • “2147483646”(数值为INT_MAX-1)

    这种情况具体为下面的判定条件

    (sum==INT_MAX/10||sum==(INT_MAX-char2int(s[p]))/10)

  • “-2147483647”(数值为INT_MIN+1)

    要求我们使用一个标记bool overflow 记录,假如sum得到了INT_MAX,这是因为溢出了还是sum值就为INT_MAX

INT_MIN与INT_MAX的取值

本题的关键点在于,给出的string其真值有可能在int类型的范围之外。对这种数值的处理方式,题目的描述如下:

如果整数数超过 32 位有符号整数范围 [$−2^{31}$, $2^{31} − 1$] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 $−2^{31}$ 的整数应该被固定为 $−2^{31}$ ,大于 $2^{31} − 1$ 的整数应该被固定为 $2^{31} − 1$ 。

这引发了我对这几个数值的总结欲望。

int类型的长度为4B,也就是32位。使用补码存储的情况下,正数的最高位为0,负数的最高位为1,则:

INT_MAX=$2^{31}-1$={01111111111111111111111111111111}=0x7fffffff

INT_MIN=$-2^{31}$={10000000000000000000000000000000}=0x80000000