面试题strtoi实现(一)—— 函数的简单实现

最近参加了一场面试,面试官给出的一道面试题是实现strtoi,结果悲催的跪倒在 这道题上。 当时赶去 面试

的时候太匆忙,居然还找错地方了。见到面试官的时候已经迟到了。到了后头一直晕。。。结果可想而知。


当然,给自己找了主观上的借口,还是得客观的分析下为啥那个程序没有完整的写出来。头晕的我,当时

精力不太集中,一边想着程序的大体框架,一边又不断地考虑各种错误检查和处理,又考虑着题目中一些没有

明确说明的情况。结果什么都没做好:错误处理考虑到了很多情况,但不完备,并且零散地分部在if语句中,

其实想清楚后是可以分好类的。至于程序框架部分,写了个七七八八,但还是没写好。


事后,分析和总结了这次失利的情况。内功有待增强,临场发挥很欠缺,特别不该在匆忙,欠准备中做事情。

当然,针对这类写程序的问题:(1)优先写出大体程序框架 (2)考虑错误检查及处理,针对题目中不明晰的

地方请教面试官。毕竟,错误检查及处理未做好,顶多就算考虑不完备;要是程序的大体框架,主体逻辑都没

写好,那就给别人“写不出程序”的印象了。


     好了,说了那么多废话,咱们回到正题,来看看面试题,并找找解决思路吧。题目是用英文描述的,我也

记不得具体描述了。需要考虑2~32进制;出错时将end_ptr指向第一次发现的非法字符的位置;还需要考虑

溢出情况;从描述上来看,合法的输入数据的格式为

[若干空格符,制表符]  [正负号]  [标明进制的字符]  [数字字母串]  [字符串结束符]

    

     在百度百科里找了个相关的描述。

      

题目描述:实现my_strtoi函数,完成字符串到整型数值的转换。

函数定义

int my_strtoi(const char *src_str,char **end_ptr,int base);

函数说明

       这个函数会将参数src_str字符串根据参数base来转换成整型数。

        参数base范围从2至36,或0。参数base代表采用的进制方式,如base值为10则采用10进制,若base值

为16则采用16进制等。当base值为0时则是采用10进制做转换,但遇到如’0x’前置字符则会使用16进制做

转换、遇到’0’前置字符而不是’0x’的时候会使用8进制做转换。

        一开始strtoi()会扫描参数src_str字符串,跳过前面的空格字符,直到遇上数字或正负符号才开始转换,

再遇到非数字或字符串结束时('\0')结束转换,并将结果返回。若参数end_ptr不为NULL,则会将遇到不合条件

而终止的src_str中的字符指针end_ptr返回;若参数end_ptr为NULL,则会不返回非法字符串。


         OK,按照我们上面总结的,先来“画出”程序的主题逻辑

(1)通过while循环,跳过前导空格符或者制表符。需要注意的是指针自增要放到while循环里,而不是在循环

条件里,因为后者会导致指针多移动了一个位置,指向空格,制表符后的第二个非空格字符;要是输入字符串

只有空格怎么办?那么此时指向的将是'\0'后面的那个字符。也就是指针越界,访问了“非法内存”。

(2)发现了" + "或者" - "时,记录下数值的符号类型,将指针往后移一位;没发现的情况,也是当做”正值“

处理,但指针不向后移动。

(3)处理数字或者字母。如何将它们转int呢?对于扫描”123“字符串,转换为整型数,有两种方式:从左往右

扫描,也就是从”最高位“。扫描到1,记录下来,当扫描到2时,怎么办?1 * 10 + 2 = 12 。那接下来扫描到3

怎么办? 12 * 10 + 3 = 123 。 如果是从右往左扫描呢? 那就相当于从”最低位“计入。扫描到3,计入。接着扫描

到2,就是2 * 10 + 3 = 23 。 再扫描到了1,那么就是1* 10 * 10 + 23 = 123 。[扫描数字字符] - '0' + 10 就是该数字

字符所表示的数值。

          在字符串格式已经给定,我们可以通过类似strlen这样的函数快速求得字符串长度的情况下,两种方法都

可行。但如果追求更高效,还是从左到右扫描,毕竟求字符串长度,也是要耗时的。这里只是提供给大家这

两种思路。我们的程序采用从左到右扫描输入字符串

          那如果是字母呢? 大小写同等视之。如果是'a',我们按照数值10来对待;如果是'Z',我们按照35对待。

也就说,单个字母和数字所能表示最大数值35。现在知道为什么我们所能支持的最大进制为36了吧?

[扫描字母] - 'a' + 10 (小写)或者[扫描字母] - 'A' + 10 (大写)就是该字母所表示的数值。

(4)扫描到字符串结束符'\0',非法字符或者数值溢出时,扫描循环结束,返回结果。

        

    接下来就是考虑错误情况及题目未明晰部分了。

(1)输入字符串为NULL。

(2)输入字符串中仅包含'\0',或者仅包含在空格,制表符。

(3)扫描过程中遇到非法字符。可以是在扫描前导空格,制表符过程中;也可以是在要扫描”数值符号“字符;

也可以是在扫描后面的数字,字母字符。

(4)扫描到的数值溢出,也就是"小于” INT_MIN(如-2147483648),或者“大于”INT_MAX(如2147483647),

此时也要结束处理。注意,此处的“小于”,“大于”的比较,是不能通过int类型的数值比较进行的,因为整型的

两个数相加,结果会溢出,直接数值比较,肯定会得出错误的结果。

          但我们知道unsigned int是能表示比int更广的数值范围的,是否可以通过直接将扫描的数值的正值(累加

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值