leetcode 8: (剑指offer 面试题49)
8. String to Integer (atoi)
Implement atoi (myAtoi) 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.
Update (2015-02-10):
The signature of the C++
function had been updated. If you still see your function signature accepts a const char *
argument, please click the reload button to reset your code definition.
The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.
The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.
If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.
If no valid conversion could be performed, a zero value is returned. If the correct value is out of the range of representable values, INT_MAX (2147483647) or INT_MIN (-2147483648) is returned.
注: 费马质数(Fermat number) F(n) = 2^(2^n) + 1,F(6)=18446744073709551617=2^64+1 (65位的数),9223372036854775807=2^63-1. 测试用例中的部分数来源于此。可以顺便记录转换后的长度newlen,如果值越出[INT_MIN, INT_MAX](或 长度newlen超过11),提前输出INT_MAX,如果为负数则输出INT_MIN.
leetcode AC代码:
#include<iostream> #include<string> using namespace std; class Solution { public: int myAtoi(string str) { if(str=="") return 0; // str.length()==0 等价于 str=="",故条件不必写为if(str=="" || str.length()==0) long long final, res=0; int len=str.length(); int sign=1; int sign_count=0; for(int i=0; i<len; i++) { char ch=str[i]; if(ch=='-' || ch=='+') sign_count++; if(sign_count<=1) { if(ch<='9' && ch>='0') { res = res*10+ch-'0'; if(res> INT_MAX && sign==1) return INT_MAX; // 当输入数超过INT_MAX或INT_MIN时,需及时退出,如果等计算完再返回,final会变为1(存储越界) if(res< INT_MIN && sign==-1) return INT_MIN; if(i+1<len && str[i+1]==' ') break; } else if(ch=='-' || ch=='+') { if(ch=='-') sign=-1; if(i+1<len && str[i+1]==' ') break; } else if(ch==' ') ; // 开头的空格忽略掉 else break; // 输入不合法,退出循环 } else return 0; } if(res>= INT_MIN && res <= INT_MAX) final=res*sign; else if(sign==1) final = INT_MAX; else if(sign==-1) final = INT_MIN; // 如果越出整数边界,返回相应的值 return final; // -2147483648[(signed int)0x80000000] ~ 2147483647(0x7FFFFFFF) } }; // 以下为测试 int main() { string str0; // str0.size() == 0; // 后面的半句:可写可不写,字符串默认初始化为空串 string str1="1ab3"; // 应返回1 string str2="18446744073709551617"; string str3="- +899999 "; string str4=" 010"; // 应返回10 string str5=" +0 123"; string str6="13 456"; // 123 string str7=" - 321"; Solution sol; cout<<sol.myAtoi(str0)<<endl; cout<<sol.myAtoi(str1)<<endl; cout<<sol.myAtoi(str2)<<endl; cout<<sol.myAtoi(str3)<<endl; cout<<sol.myAtoi(str4)<<endl; cout<<sol.myAtoi(str5)<<endl; cout<<sol.myAtoi(str6)<<endl; cout<<sol.myAtoi(str7)<<endl; return 0; }
Submission Details:
Accepted
1047 / 1047 test cases passed.
ps: 在leetcode中提交代码的过程中遇到了下面这个error: control reaches end of non-void function [-Werror=return-type],而本地的visual studio和Dev C++上没报错,这是由于所提交的代码中带返回值的函数不一定能return而导致的错误。比如将return放进了if else判断语句里面,如果那个判断语句一直不执行那么就没有返回值了,就会报此错。于是可将需要返回的值都放进同一个变量final中,最后return final即可.
相关链接: http://stackoverflow.com/questions/30402164/control-reaches-end-of-non-void-function-werror-return-type
class Solution { public: int StrToInt(string str) { if(str=="") return 0; long long res=0; int len=str.length(); int isPositive=1; for(int i=0; i<len; i++) { char ch=str[i]; if(ch<='9' && ch>='0') res = res*10+ch-'0'; else if(ch=='-') isPositive=-1; else if(ch=='+') ; // 不处理,继续往后扫 else return 0; } return res*isPositive; } };
严格参考《剑指offer》2014版 原书的写法:
1、设置输入合法标志,默认为false,当第一个字符为空或者\0的时候直接诶返回0,输入合法标志为false。反之进入下一步。
2、设置符号位,判断是+还是-还是不带符号位,只有为-才置为true,否则均为false。
3、区分除了符号位之外第一位时候合法输入。非法时返回0,输入合法位为false。合法时判断有无越界,若越界返回0,输入合法位为false,无越界计算num返回,输入合法位为true。
总结:只有在顺利走到字符串尾部的时候输入合法标志位才为true,其余情况均为false。这样就能区分开返回0时究竟是非法输入还是确实输入的就是0。只有一个+号或-号也被考虑进来了,直接返回0且输入合法标志位为false。
class Solution { public: enum Status{kValid = 0,kInvalid}; int g_nStatus = kValid; int StrToInt(string str) { g_nStatus = kInvalid; long long num = 0; int index=0; if((!str.empty())&&str[index]!='\0') { bool minus = false; if(str[index]=='+') index++; else if(str[index]=='-') { index++; minus = true; } if(str[index]!='\0') { int length=str.size(); num = StrToIntCore(str.substr(index,length-index),minus); } } return (int)num; } long long StrToIntCore(const string& digit,bool minus) { long long num=0; int i=0; while(digit[i]!='\0') { //合法情况 //if(digit[i]=='+'||digit[i]=='-') //i++; if(digit[i]>='0'&&digit[i]<='9') { int flag = minus?-1:1; num = num*10+ flag*(digit[i]-'0'); //越界情况 if((!minus&&num>0x7FFFFFFF)||(minus&&num<(signed int)0x80000000)) { num = 0; break; } i++; } else//非法情况 { num = 0; break; } } if(digit[i]=='\0') g_nStatus = kValid; return num; } };