LeetCode(8)StringToInteger
2013-12-04 08:18
225 查看
本题要求自己实现atoi函数,输入为一个string,输出为相应的int型integer.主要考察能否全面地考虑到输入的不同情况。比如以下的一些情况:
1. 输入"" 期待输出0
2. 输入" " 期待输出0
3. 输入" -a4" 期待输出0
4. 输入" -" 期待输出0
5. 输入" 90 " 期待输出90
6. 输入"-3 " 期待输出-3
7. 输入"5abc3" 期待输出5
8. 输入"004" 期待输出4
9. 输入"0.3" 期待输出0
10. 输入"2147483648" 期待输出 2147483647(题目给定了一个溢出的范围为[INT_MIN, INT_MAX],这个数溢出了,所以输出INT_MAX,取值为2147483647)
11. 输入"-2147483649" 期待输出 2147483647(题目给定了一个溢出的范围为[INT_MIN, INT_MAX],这个数溢出了,所以输出INT_MIN,取值为-2147483648)
代码如下
小结:
(1) 考虑清楚各种情况
(2) 溢出的处理需要小心。首先使用了long long型变量作为中间变量result来存储结果,这样避免了发生int型的溢出。
(3) 溢出的处理需要小心。其次注意第9行和第10行
这么写是因为如果写为
的话,得到的结果不是希望得到的2147483648而是2147483647,猜测可能是因为在没有转化为long long时,INT_MIN会由于int的溢出,所以0-INT_MIN得到的是INT_MAX而不是INT_MIN的绝对值。(我的测试平台是mac 64位Xcode。)
(4) 溢出是什么?
溢出简单地说,就是要表示的数太巨大了,变量类型装不下了。
在C++中,整型的溢出分为signed 和unsigned 2种情况。unsigned在面对表示的巨大的数的情况下,是有固定的规则的,所以也可以叫做unsigned不会溢出。而signed是undefined behavior,即是未定义的行为。
以unsigned int为例来看看,在mac 64中,unsigned int的取值范围为[0~4294967295].
unsigned int aa=4294967295;
aa=aa+1; //结果为aa=0
aa=aa+1; //结果为aa=1
aa=4294967295+1; //结果为aa=0
所以,遇到一个极大的unsigned int数,只需要用它取模4294967296就知道了它的最终值。
在signed int中,由于历史原因,表示正负数的方式有一些差异,所以没法给出一个确定的结果。很多情况是,两个巨大的正数相加,结果是个负数。这就是发生了溢出。
搜到一份linux的atoi函数的源码,基本思路也差不多,贴在下面。
update: 2014-12-16
下面的解法没有使用long来存当前的result,而是使用int ,在result可能累加过界超过INT_MAX的时候就根据情况返回INT_MAX或者INT_MIN了。
1. 输入"" 期待输出0
2. 输入" " 期待输出0
3. 输入" -a4" 期待输出0
4. 输入" -" 期待输出0
5. 输入" 90 " 期待输出90
6. 输入"-3 " 期待输出-3
7. 输入"5abc3" 期待输出5
8. 输入"004" 期待输出4
9. 输入"0.3" 期待输出0
10. 输入"2147483648" 期待输出 2147483647(题目给定了一个溢出的范围为[INT_MIN, INT_MAX],这个数溢出了,所以输出INT_MAX,取值为2147483647)
11. 输入"-2147483649" 期待输出 2147483647(题目给定了一个溢出的范围为[INT_MIN, INT_MAX],这个数溢出了,所以输出INT_MIN,取值为-2147483648)
代码如下
class Solution { public: int atoi(const char *str) { // IMPORTANT: Please reset any member data you declared, as // the same Solution instance will be reused for each test case. long long result = 0; int index=0; bool is_positive=true; long long long_int_min_abs=INT_MIN; long_int_min_abs=0-long_int_min_abs; //std::cout<<"a="<<a<<std::endl; //std::cout<<"a="<<-INT_MIN<<std::endl; while(str[index]==' '){ index++; } if(str[index]=='\0') { //空串 return 0; } if(str[index]=='+') {//有正号 is_positive=true; index++; } else if(str[index]=='-') {//有负号 is_positive=false; index++; } else if( (str[index]-'0'>=0) && (str[index]-'0'<=9) ) {//无正号无负号,是数字 is_positive=true; } else { return 0; //无法做任何转换的不规则串 } while((str[index]-'0'>=0)&&(str[index]-'0'<=9)) { int digit=str[index]-'0'; result=result*10+digit; index++; //std::cout<<"digit="<<digit<<",result="<<result<<std::endl; if((result>INT_MAX)&&(is_positive==true)) return INT_MAX; if((result>long_int_min_abs)&&(is_positive==false))//等价于result<abs(INT_MIN) return INT_MIN; } if(is_positive==false) result=-result; return (int)result; } };
小结:
(1) 考虑清楚各种情况
(2) 溢出的处理需要小心。首先使用了long long型变量作为中间变量result来存储结果,这样避免了发生int型的溢出。
(3) 溢出的处理需要小心。其次注意第9行和第10行
long long long_int_min_abs=INT_MIN; long_int_min_abs=0-long_int_min_abs;
这么写是因为如果写为
long long long_int_min_abs=0-INT_MIN;
的话,得到的结果不是希望得到的2147483648而是2147483647,猜测可能是因为在没有转化为long long时,INT_MIN会由于int的溢出,所以0-INT_MIN得到的是INT_MAX而不是INT_MIN的绝对值。(我的测试平台是mac 64位Xcode。)
(4) 溢出是什么?
溢出简单地说,就是要表示的数太巨大了,变量类型装不下了。
在C++中,整型的溢出分为signed 和unsigned 2种情况。unsigned在面对表示的巨大的数的情况下,是有固定的规则的,所以也可以叫做unsigned不会溢出。而signed是undefined behavior,即是未定义的行为。
以unsigned int为例来看看,在mac 64中,unsigned int的取值范围为[0~4294967295].
unsigned int aa=4294967295;
aa=aa+1; //结果为aa=0
aa=aa+1; //结果为aa=1
aa=4294967295+1; //结果为aa=0
所以,遇到一个极大的unsigned int数,只需要用它取模4294967296就知道了它的最终值。
在signed int中,由于历史原因,表示正负数的方式有一些差异,所以没法给出一个确定的结果。很多情况是,两个巨大的正数相加,结果是个负数。这就是发生了溢出。
搜到一份linux的atoi函数的源码,基本思路也差不多,贴在下面。
long __cdecl atol( const char *nptr ) { int c; /* current char */ long total; /* current total */ int sign; /* if '-', then negative, otherwise positive */ /* skip whitespace */ while ( isspace((int)(unsigned char)*nptr) ) ++nptr; c = (int)(unsigned char)*nptr++; sign = c; /* save sign indication */ if (c == '-' || c == '+') c = (int)(unsigned char)*nptr++; /* skip sign */ total = 0; while (isdigit(c)) { total = 10 * total + (c - '0'); /* accumulate digit */ c = (int)(unsigned char)*nptr++; /* get next char */ } if (sign == '-') return -total; else return total; /* return result, negated if necessary */ }
update: 2014-12-16
下面的解法没有使用long来存当前的result,而是使用int ,在result可能累加过界超过INT_MAX的时候就根据情况返回INT_MAX或者INT_MIN了。
class Solution { public: int atoi(const char *str) { //space //validate 0~9 //+- //0012 vs 1002 //INTMAX int result = 0; bool isNegative = false; while(*str == ' ') str++; if(*str == '+') str++; else if(*str == '-') { isNegative = true; str++; } while(*str != '\0') { if (*str - '0' == 0 && result == 0) { str++; continue; } if (*str - '0' < 0 || *str - '9' > 0) return isNegative? -result: result; if (result > INT_MAX / 10) return isNegative? INT_MIN : INT_MAX; result *= 10; if ((*str - '0') > (INT_MAX - result)) return isNegative? INT_MIN : INT_MAX; result = result + *str - '0'; str++; } return isNegative? -result : result; } };
相关文章推荐
- LeetCode 008 StringToInteger(atoi)
- LeetCode——8. String to Integer
- [LeetCode] String to Integer (atoi)
- [LeetCode-8] String to Integer (atoi,字符串转成整数)
- 8、LeetCode--String to Integer (atoi)
- [Leetcode]String to Integer (atoi)
- [LeetCode] String to Integer(atoi)
- leetcode 第8题 String to Integer(atoi)
- 【leetcode】8. String to Integer (atoi)
- leetcode之String to Integer
- leetcode 8. String to Integer (atoi)
- LeetCode (8) String to Integer (atoi) C语言程序
- LeetCode 8:《String to Integer (atoi) 》
- String to Integer (atoi) -- LeetCode
- leetcode 8. String to Integer (atoi)
- LeetCode 8 String to Integer (atoi)
- Leetcode-8. String to Integer (atoi)
- leetcode-String to Integer (atoi)
- LeetCode(8)String to Integer (atoi)
- LEETCODE: String to Integer (atoi)