字符串转换成整数
微软面试题之中的一个,难度系数低。
题目描写叙述例如以下:输入一个表示整数的字符串,把该字符串转换成整数并输出。
比如输入字符串"345"。则输出整数345。
逻辑分析:
1、对于面试者来说,遇到这样的题,算是非常幸运的,比起思维灵活度,本题更加注重基础。也就是说,代码的稳定性,健壮性一定要好。对C/C++比較熟悉的读者应该非常快会想到一个函数:atoi,没错。标准库中的atoi就是将字符串转为整数的函数。尽管如此。但却非常少有人尝试去了解atoi这个函数的内部实现,窃以为,atoi的实现,事实上和str*系列函数同等重要。
2、说到稳定性,就要考虑几个easy引起问题的地方。函数模型int atoi(char* str);,那么第一点要考虑的。当然是str是否为空。另外,str中的字符仅仅可能存在三种情况:- | + | [0..9],假设存在其它字符,那么则视为非法字符。最后一点,也是最easy忽略的,要考虑溢出问题。
给出代码:
#include <stdio.h> #include <limits.h> int atoi(char *str) { bool neg = true; char *p = str; int num = 0; if(str == NULL) { printf("字符串为空!你TM是在逗我吗?\n"); return 0; } if(*p == '-') { p++; neg = false; }else if(*p == '+') { p++; } while(*p != '\0') { if(*p>='0' && *p <= '9') { num = num * 10 + (*p - '0'); if(num > INT_MAX) { printf("溢出!\n"); return 0; } } else { printf("错误!输出:含非法字符\n"); return 0; } p++; } if(neg == false) num = -num; return num; } int main() { char str[4][10] = {"123456789","+23","-45","XiaoJ8"}; for(int i=0; i<4;i++) { printf("%d\n",atoi(str[i])); } return 0; }
3、乍看起来。我们好像完毕了任务,可是实际上。当我写完上述代码之后,立马反悔了。非常多读者应该也察觉到了。上述代码有一个非常严重的漏洞,我们都知道由于补码的形式存储。负整数的绝对值上限是要比正整数上限大1的,而我们推断的分支。显然漏掉了负上限。再细致考虑,就会发现,事实上判别代码从一開始就错了。并且是全然错了。高级语言不是汇编。我们无法通过CF,OF之类的(无符号当然是CF)标志位来判别。而在我们的程序中。num是永远不可能大于INT_MAX的,由于当num超过了这个值。则会自己主动溢出。变为一个非常小的值,再去比較显然没有意义。正确的处理。是要对照计算前后的num,假设计算后的值小于计算前,显然发生了溢出(想想为什么)。
第二种处理方式,就是从位数进行比較,显然后者略麻烦一些,倒也不失为一种思路。
代码不再纠正,兴许工作由读者完毕。