的时候太匆忙,居然还找错地方了。见到面试官的时候已经迟到了。到了后头一直晕。。。结果可想而知。
当然,给自己找了主观上的借口,还是得客观的分析下为啥那个程序没有完整的写出来。头晕的我,当时
精力不太集中,一边想着程序的大体框架,一边又不断地考虑各种错误检查和处理,又考虑着题目中一些没有
明确说明的情况。结果什么都没做好:错误处理考虑到了很多情况,但不完备,并且零散地分部在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更广的数值范围的,是否可以通过直接将扫描的数值的正值(累加