8. 字符串转换整数 (atoi) - 力扣(LeetCode)
先明确几条规则:
- 开头是空格,直接跳过
- (跳过空格之后)第一个字符可以是’+’,’-’,和数字,如果是其他的直接返回0
- 正负号之后的第一个字符必须得是数字,否则返回0
- 一直将连续的数字字符组合起来,直到碰到下一个非数字字符
- 如果组合后的数字溢出,则返回0
如何判断溢出,和LeetCode第 7 题:整数反转(C++)_qq_32523711的博客-CSDN博客如出一辙。
字符全为空的时候,访问str[i]会不会越界,关于string的末尾会不会访问越界可以看这儿:
class Solution {
public:
int myAtoi(string str) {
int i = 0, flag = 1;//flag用于标识正负,默认为正数
long res = 0; //因为要与INT_MAX进行比较
while(str[i] == ' ') ++i;//跳过空格
if(str[i] == '-'){
flag = -1; ++i;
}else if(str[i] == '+') ++i;
if(str[i] < '0' || str[i] > '9') return 0; //第一个有效字符不是数字
while(i < str.size() &&str[i] >= '0' && str[i] <= '9'){
res = 10*res + str[i++]-'0';
if(res >= INT_MAX && flag == 1) return INT_MAX;//使用long类型提前排判断溢出
if(res > INT_MAX && flag == -1) return INT_MIN;
}
return flag * res;
}
};
如果不使用long,也还是可以判断是否会溢出的,简单来说就是乘法转化为除法,提前与INT_MAX/10进行比较。
class Solution {
public:
//INT_MAX = 2147483647
//INT_MIN = -2147483648
int myAtoi(string str) {
int i = 0, flag = 1;//flag用于标识正负,默认为正数
int res = 0; //因为要与INT_MAX进行比较
while(str[i] == ' ') ++i;//跳过空格
if(str[i] == '-'){
flag = -1; ++i;
}else if(str[i] == '+') ++i;
if(str[i] < '0' || str[i] > '9') return 0; //第一个有效字符不是数字
while(i < str.size() &&str[i] >= '0' && str[i] <= '9'){
if(res > INT_MAX/10) return flag == 1 ? INT_MAX : INT_MIN; //铁溢出
if(res == INT_MAX/10){ //有可能溢出
if(flag == 1 && str[i]-'0' >= 7) return INT_MAX;
if(flag == -1 && str[i]-'0' >= 8) return INT_MIN;
}
res = 10*res + (str[i++]-'0'); //一定要有括号,不然可能溢出
}
return flag * res;
}
};
看题解里还有说到有限状态机的解法,后续再补。