犹记得July大大在今年交大一次读书会上让大家10min写这个算法,然后讲解这个算法,我是通过百度网盘的视频看的,我10min没写出来,而且还是在输出exception case的几次提示下才AC掉的,而且关于需求分析还差了cplusplus的说明= =
今天写了这个函数,一开始想估计有千万种情况考虑,但是细细一想,其实也是可以枚举出来的,关键就是逻辑要能处理所有的case,
我已开始居然连需求都没弄清楚,他是允许非法字符的,只要前面有一些可以产生数值的,例如-9a.986返回-9,-9.a8a77a 返回-9,这感觉有点奇怪,我觉得出现非 + - . 0-9的就都是非法了,不知道系统设计出于什么目的。
设计逻辑了,前缀我主要分为4种:
1) [+|-] [(0-9)上加号] [非法或.]
2) [(0-9)上加号] [非法或.]
3) [+ | -] .
4) .
主要分为这些,然后先看第一个是否符号位,是的话i++, 然后这时判断i是否越界(每次i++ i--都要判断是否可能越了上下界,有的话就特殊处理,我又一次就这么错了),如果是的话,说明只有符号位,返回非法字符。否则从后面找连续的数字,然后同时loop 要判断是否越界,发现越界可以统一处理~ 然后后面算值,这部分比较简单,我又一次居然直接用ASCII码算= = 然后最后如果负数的话,根据之前的 符号判断,sum-=2*sum, 我出现正负数一起处理都是这样把两者统一成正数处理,这样逻辑比较清晰。
还有最最难想到的就是溢出了,从给的case来看如果上溢返回上届,下溢返回下届,所以需要再加完之后就判断,我之前还在最后判断发现已经没用了,sum已经因为溢出错了= = 然后如果上溢了,就返回上届,因为int是补码范围,负变正后负数最大会多一个,也即-2^31,但是发现这个case可以统一到里面,因为2^31溢出恰好变为-2^31,于是直接返回下届是对的。
我还有一次直接写2^31-1结果就不知道C++认为是什么了= =我有时候还会犯从数学到代码转换的一个缺口,甚至左右赋值都写错过一次,感觉程序设计和数学思维会有些不同
最后的最后,附上修改几次后的代码:
int myatoi(const char* str) { string cppstr=str, intstr; istringstream istr(cppstr); int isnegative=false,i=0; while(istr>>intstr) { if(intstr.at(0)=='-') { isnegative=true; i++; } if(intstr.at(0)=='+') { i++; } if(i==intstr.size())//whether only + - return 0; if(intstr.at(i)=='.')return 0; int starti=i; while(i<intstr.size()&&intstr.at(i)<='9'&&intstr.at(i)>='0') i++; int endi=i-1; int sum=0,weighti=0; for(int k=endi;k>=starti;k--,weighti++) sum+=(intstr.at(k)-'0')*pow(10.0, weighti); if(sum<0) //overflow { if(isnegative==false) return pow(2.0,31)-1; else return -pow(2.0,31); } if(isnegative==true) sum-=2*sum; return sum; } if(intstr.size()==0)return 0; }
July大神交大读书会子atoi,布布扣,bubuko.com
原文地址:http://blog.csdn.net/richardzrc/article/details/31065849