每日算法之八:String to Integer (atoi) 及溢出分析

来源:互联网 发布:sql 合计多列数据 编辑:程序博客网 时间:2024/06/11 17:52

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;}

我们使用这种方法就可以进行溢出的判断,这是苹果安全编码的建议,应该是可用高效的。

因为溢出导致的异常是常见并且是难以发现的,因此一定要注意。

1 0
原创粉丝点击