Implement atoi to convert a string to an integer. Hint: Carefully consider all possible input cases. If you want a challenge, please do not see below and ask yourself what are the possible input cases.Notes: It is intended for this problem to be specified vaguely (ie, no given input specs). You are responsible to gather all the input requirements up front.
要求就是把字符串转化为整形,按照我们的理解就可以逐字符遍历,转化为整形即可,比如字符串"123454",我们只要取出第零个字符'1'-‘0’就可以得到数字1,然后把1乘以10,再加上‘2’-‘0’·····这样依次就可以得到转化之后的整形数字。当然有几个地方需要注意:
1)字符串可能以正负号开始,也可能包含一些其他的非数字型字符,是不能转化为数字的,是忽略还是报错看需求
2)越界,字符串转化到整形数字之后的数字串可能超出表示范围,超出的可以置为INT_MAX或者INT_MIN。
代码参考如下:
class Solution {
public:
int atoi(const char *str) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
long long ret = 0;//存储最终转化的数字
const char *p = str;
while(*p == ' ') p++;//忽略空格
bool valid = true;
while(valid && *p == '+') {
valid = false;
p++;
}
while(*p == '0') p++;
bool minus = false;
if(*p == '-'){
minus = true;
p++;
}
while(*p != '/0'){
if(*p >= '0' && *p <='9'){
ret = ret * 10 + *p - '0';
if(!minus && ret > INT_MAX) return INT_MAX; // positive and overflow
if(minus && -ret < INT_MIN) return INT_MIN; // negative and overflow
p++;
} else { // no digit then break
break;
}
}
return minus ? -ret : ret;
}
};
这里需要特别注意的就是怎么预防溢出,如果都是int类型,用ret+1>INT_MAX进行判断是错误的,当ret是INT_MAX时,再进行加一操作是会溢出的,变为最小的负数,对计算机而言对符号性的整数是进行位运算的,即对INT_MAX:0111 1111 1111 1111 1111 1111 1111 1111 进行加1之后就变为
1000 0000 0000 0000 0000 0000 0000 0000也就是INT_MIN。实质上产生的进位到了符号位。上面能AC的原因是使用了long long (8字节)类型的整形存储int(4字节)。所以能够判断大于INT_MAX,现在假定形参也是longlong类型或者不允许使用刚才的方式,那么我们应该怎么做呢?
#include <limits.h>
void f(signed int si_a, signed int si_b) {
signed int sum;
if (((si_b > 0) && (si_a > (INT_MAX - si_b))) ||
((si_b < 0) && (si_a < (INT_MIN - si_b)))) {
/* Handle error */
return;
}
sum = si_a + si_b;
}
我们使用这种方法就可以进行溢出的判断,这是苹果安全编码的建议,应该是可用高效的。
因为溢出导致的异常是常见并且是难以发现的,因此一定要注意。