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; }
我们使用这种方法就可以进行溢出的判断,这是苹果安全编码的建议,应该是可用高效的。
因为溢出导致的异常是常见并且是难以发现的,因此一定要注意。
每日算法之八:String to Integer (atoi) 及溢出分析,布布扣,bubuko.com