字符串转换成整数

微软面试题之中的一个,难度系数低。

题目描写叙述例如以下:输入一个表示整数的字符串,把该字符串转换成整数并输出。 

比如输入字符串"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,假设计算后的值小于计算前,显然发生了溢出(想想为什么)。

第二种处理方式,就是从位数进行比較,显然后者略麻烦一些,倒也不失为一种思路。



代码不再纠正,兴许工作由读者完毕。


posted @ 2017-06-26 14:36  yangykaifa  阅读(354)  评论(0编辑  收藏  举报