atoi函数从初步实现到完美优化

327 阅读4分钟

@TOC

一. atoi函数简介

aoti把字符串转化成整型的一个函数

先看怎么使用

在这里插入图片描述 传入一个字符类型的指针 变成一个整型的数据

话不多说 咱直接上代码

int main()
{
	char arr[20] = "1234";
	int a = atoi(arr);
	printf("%d", a);
	return 0;
}

代码演示的效果如下

在这里插入图片描述

二. 简单实现

现在同学们大概了解了atoi这个函数怎么使用了吧

我们先来看看大概怎么实现这个函数

在这里插入图片描述

我们大概用代码来实现一下

int my_atoi(char* str)
{
	int n = 0;
	while (*str)
	{
		n = n * 10 + (*str - '0');
		str++;
	}
	return n;
}

我们来看看效果

在这里插入图片描述

能跑

但是! 如果你再面试的时候 回答这个实现方式的话 你很可能就要接受面试官的 压力测试了!

三. 面试官的压力测试

面试官: 我觉得你刚刚这个实现想法很好 但是你有没有考虑过这样子的情

况呢?

如果传入的是空指针怎么办呢?

如果传入的是空字符串怎么办呢?

如果传入的是非数字字符怎么办呢?

如果前面有空白字符怎么办呢?

如果前面有正负号怎么办呢?

除了我上面的说的那些问题是否还存在其他的问题呢?

这些你刚刚写的函数可以解决吗?

我: 鹅 我知道你很急 但是你先听我说

你先别急

我们这样来优化

四. 完美优化

4.1 空指针解决

首先 空指针的问题是我们最不能容忍的 这时候我们需要先断言一下

assert(str);

在键盘上轻轻的敲上这一行代码 空指针的问题就被我们解决啦

4.2 字符串为空

如果传入的是一个空字符串的话 判断起来很简单

第一个字符就是\0

	if (*str=='\0')
	{
		return 0;
	}

那么 如果我们判断到了是空字符串 我们返回什么呢?

仔细一想 好像返回什么都不合适

那么我们这里做这样一件事

**我们枚举两个变量 合法 和 非法 **

因为很多输出都是非法操作

所以首先将状态设为非法

代码表示如下

enum Status
{
	VALUD,
	INVALUD
};

enum Status status = INVALUD;

4.3 字符串前面为空

如果 我们发现一个字符串的前面是空白字符 那么我们只需要将它跳过去就可

以了 这里有两种解法

while (*str==' ')
	{
		str++;
	}

4.4 正负号

这个也很简单

我们可以设置一个记号标志 flag

我们在遍历前面的时候 如果遍历到正号 falg就赋值为1

如果遍历到负号 falg就赋值为-1

如果什么符号都没有 那就默认是正数

所以说我们将flag的初始值赋值为1

	// 正负号
	if (*str =='+')
	{
		flag = 1;
		str++;
	}
	else if (*str=='-')
	{
		flag = -1;
		str++;
	}

4.5 非数字字符

这里我们遍历字符串 如果遍历到非数字字符 其实再遍历下去也没有什么意义

所以说 我们遇到非数字字符就停止遍历 抛出异常

	while (isdigit( * str))
	{
		n = n * 10 + (flag)*(*str - '0');
		str++;
	}

4.6 越界问题

如果说 n比最小值还小 比最大值还大 那就说明数字可能越界了

这里我们也需要抛出异常

但是这里我们不能使用int类型的n来存储了

否则它就会发生截断 从而不会抛出异常

所以说 我们将 n的类型定义为 long long

			if (n<INT_MIN || n>INT_MAX)
			{
				n = 0;
				break;
			}

4.7 最后检查

最后 如果说上面的错误一个都没有发生 很顺利的进行到程序的最下面了

那么我们可以在程序的最后面将状态改为合法

	if (*str=='\0')
	{
		status = VALUD;
	}

五 完整代码加试运行

优化完成之后我们邪魅一笑

将源码甩给面试官

enum Status
{
	VALUD,
	INVALUD
};

enum Status status = INVALUD;


int my_atoi(char* str)
{
	long long n = 0;
	int flag = 1;
	assert(str);

	//字符串为空
	if (*str=='\0')
	{
		return 0;
	}

	//字符串前面为空
	//while (*str==' ')
	//{
	//	str++;
	//}
	while (isspace(*str))
	{
		str++;
	}

	// 正负号
	if (*str =='+')
	{
		flag = 1;
		str++;
	}
	else if (*str=='-')
	{
		flag = -1;
		str++;
	}

	while (*str !='\0')
	{
		if (isdigit(*str))
		{
			n = n * 10 + (flag) * (*str - '0');
			if (n<INT_MIN || n>INT_MAX)
			{
				n = 0;
				break;
			}
			str++;
		}
		else
		{
			break;
		}
	}

	if (*str=='\0')
	{
		status = VALUD;
	}

	return n;
}

int main()
{
	char arr[20] = "12a34";
	int num = my_atoi(arr);
	if (status==VALUD)
	{
		printf("%d ", num);
	}
	else if (status==INVALUD)
	{
		printf("非法数字%d ", num);
	}
	return 0;
}

在这里插入图片描述 在这里插入图片描述

以上就是本篇博客的全部内容啦 由于博主才疏学浅 所以难免会出现纰漏

希望大佬们看到错误之后能够不吝赐教 在评论区或者私信指正 博主一定及时修正

那么大家下期再见咯