(leetcode)8. 字符串转换整数 (atoi) 详解+代码(C语言)

目录

分析算法 

第一条 

代码实现 

 第二条

代码实现

第三条  第四条 第五条 第六条 要一起看

代码实现 

 完整代码(带主函数)

 力扣通过代码(只有函数)


 

第一个力扣中等题,确实不简单,差点给我干趴下

不过通过之后真的太快乐了,一个良好的开端

函数 myAtoi(string s) 的算法如下:

  • 读入字符串并丢弃无用的前导空格
  • 检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
  • 读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
  • 将前面步骤读入的这些数字转换为整数(即,"123" -> 123, "0032" -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。
  • 如果整数数超过 32 位有符号整数范围 [−231,  231 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231 的整数应该被固定为 −231 ,大于 231 − 1 的整数应该被固定为 231 − 1 。
  • 返回整数作为最终结果。
  • 注意:本题中的空白字符只包括空格字符 ' ' 。除前导空格或数字后的其余字符串外,请勿忽略 任何其他字符。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/string-to-integer-atoi
 

睁开你的眼睛认真读题!!!

睁开你的眼睛认真读题!!!

睁开你的眼睛认真读题!!! 重要的事情说三遍!

既然题目已经给出算法,那我们就一条一条来分析 

分析算法 

第一条 

读入字符串并丢弃无用的前导空格

 简单来说,就是略过字符串中的空格,注意,这个空格,必须是从头开始的,并且连续

例如 "        -42";   这种的

代码实现 

简单,就是判断这个字符是不是空格,是就i++,跳过这个字符

(leetcode)8. 字符串转换整数 (atoi) 详解+代码(C语言)_第1张图片 

 第二条

 检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。

就是判断正负

注意必须是排在最开始,或者排在空格后面的"-"或“+”才能判断正负,并且只能出现一个,或者不出现。

像这种"   -+12"   "-" "+"连着出现的,可不能判断正负 ,这种就按纯字符处理(像"ab12"),直接返回0

当然,这里我们先不讨论返回的问题,我们就先判断一下正负

代码实现

设置了个标志变量 flag ,初始为 1 ,来进行正负转换,这一位是 ’+‘ 或 ' -' 就进入 if 语句,

利用了一下三目运算符是'-',就把flag 赋值成 -1,不是flag 就还是 1,

当然这一位不是 ’+‘ 或 '-' ,那flag 就还是 1 

(leetcode)8. 字符串转换整数 (atoi) 详解+代码(C语言)_第2张图片 

 注意:这里直接用的从上边走下来的  i ,  因为要先跳过空格

第三条  第四条 第五条 第六条 要一起看

  • 读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。 
  • 将前面步骤读入的这些数字转换为整数(即,"123" -> 123, "0032" -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)
  • 如果整数数超过 32 位有符号整数范围 [−231,  231 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231 的整数应该被固定为 −231 ,大于 231 − 1 的整数应该被固定为 231 − 1 。
  • 返回整数作为最终结果

解释:只有连续的数字字符会被转换为整数,举例更好说明 

  • " 123abc" 要转成 123
  • " 12abc2355" 要转成 12
  • ''-+12334" 要转成 0  (在第二条解释了,不是做了加减法,而是这种的就行当于"ab12334")
  • "zfsa2334" 要转成 0
  • "-456"  要转成 -456

代码实现 

1.先来给错误示范

这么写会让数超出整型范围,为啥呢? 让我们来看看

  • 首先我们要知道,整型范围是-2^31,到 2^31 - 1,这也是题目要求的

也就是-2147483648到2147483647,但我劝你不要直接用这两个数写,VS编译器会报错,

(具体可以看   清海风缘  这个大佬写的博客  链接  http://t.csdn.cn/SABnx)

但是力扣不会,但我们是需要调试的

  • 我们接着来,下面代码主要出现的问题是,sum 会 溢出,超出整型范围

你看如果 ,for循环直到 sum 第一次 小于  -2147483648,但这个值是要先赋到sum里的呀,之后在循环一次(不过现在循环已经不重要了,不要在这里纠结)之后才能走到if 判断,可是这个数已经不再int 范围里了, 而sum 是 int 类型的,你要这个数怎么放,放到sum里的数是截断之后的了,谁知道是什么,更何谈判断,所以这个方法不行我们往下看正确示范

(leetcode)8. 字符串转换整数 (atoi) 详解+代码(C语言)_第3张图片 2.   正确示范

为了VS能调试,不报错,我们把-2147483648到2147483647,换为INT_MIN 和  INT_MAX(不知道是什么的,自己查一下哈)

直接用INT_MIN(-2147483648)判断会溢出,那我们就和-214748364(INT_MIN / 10)比较,然后再看字符串的下一位(此时已经到下一位了,我画个图),

(leetcode)8. 字符串转换整数 (atoi) 详解+代码(C语言)_第4张图片

  • 如果不是以上情况我们就正常返回sum,记着我们的sum最开始就是负数 ,

所以,如果flag == -1,直接返回,

  • 若flag == 1,那我们还要再来一步,三目运算符再次闪亮登场╰(*°▽°*)╯

如果sum == INT _ MIN,但现在是正数,所以就返回 INT_MAX,

如果不等,那就没超,返回sum的相反数,-sum

(leetcode)8. 字符串转换整数 (atoi) 详解+代码(C语言)_第5张图片

 完整代码(带主函数)

#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
int myAtoi(char* s)
{
	int len = strlen(s);
	//先丢弃无用的前导空格,就是跳过
	int i = 0;
	while (s[i] == ' ')
	{
		i++;
	}
	//检查下一个字符(假设还未到字符末尾)为正还是负号,
	//读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
	int flag = 1;
	if (s[i] == '-' || s[i] == '+')
	{
		//利用三目操作符,进行判断
		(s[i] == '-') ? (flag = -1) : (flag = 1);
		i++;
	}
	//读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
	int sum = 0;
	//这么写会让数超出整型范围
	  //for (; i < len && (s[i] <= '9' && s[i] >= '0'); i++)
	  //{
	  //	//整数范围 [?2^31,  2^31 ? 1]   
	  //	//小于 ?2^31 的整数应该被固定为 ?2^31 ,大于 2^31 ? 1 的整数应该被固定为 2^31 ? 1 。
	  //	//if((sum == -214748364 && s[i] >= '8') || sum < )
	  //	if (sum <= (-2147483648))
	  //	{
	  //		sum = -2147483648;
	  //	}
	  //	else
	  //	{
	  //		sum = sum * 10 - (s[i] - '0');//出来的是负数哦
	  //	}
	  //}
	for (;(s[i] <= '9' && s[i] >= '0' && sum > INT_MIN); i++)
	{
		//整数范围 [?2^31,  2^31 ? 1]   
		//小于 ?2^31 的整数应该被固定为 ?2^31 ,大于 2^31 ? 1 的整数应该被固定为 2^31 ? 1 。
		if ((sum == (INT_MIN / 10) && s[i] >= '8') || sum < (INT_MIN / 10))
		{
			sum = INT_MIN;
		}
		else
		{
			sum = sum * 10 - (s[i] - '0');//出来的是负数哦
		}
	}
	if (flag == -1)
	{
		return sum;
	}
	//flag == 1 的情况
	return (sum == INT_MIN) ? INT_MAX : -sum;
}
int main()
{
	char arr[201] = { 0 };
	scanf("%s", arr);
	int ret = myAtoi(arr);
	printf("%d\n", ret);
	return 0;
}

 力扣通过代码(只有函数)

int myAtoi(char* s)
{
	int len = strlen(s);
	//先丢弃无用的前导空格,就是跳过
	int i = 0;
	while (s[i] == ' ')
	{
		i++;
	}
	//检查下一个字符(假设还未到字符末尾)为正还是负号,
	//读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
	int flag = 1;
	if (s[i] == '-' || s[i] == '+')
	{
		//利用三目操作符,进行判断
		(s[i] == '-') ? (flag = -1) : (flag = 1);
		i++;
	}
	//读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
	int sum = 0;
	
	for (;(s[i] <= '9' && s[i] >= '0' && sum > INT_MIN); i++)
	{
		//整数范围 [?2^31,  2^31 ? 1]   
		//小于 ?2^31 的整数应该被固定为 ?2^31 ,大于 2^31 ? 1 的整数应该被固定为 2^31 ? 1 。
		if ((sum == (INT_MIN / 10) && s[i] >= '8') || sum < (INT_MIN / 10))
		{
			sum = INT_MIN;
		}
		else
		{
			sum = sum * 10 - (s[i] - '0');//出来的是负数哦
		}
	}
	if (flag == -1)
	{
		return sum;
	}
	//flag == 1 的情况
	return (sum == INT_MIN) ? INT_MAX : -sum;
}

 (leetcode)8. 字符串转换整数 (atoi) 详解+代码(C语言)_第6张图片

 ╰(*°▽°*)╯╰(*°▽°*)╯╰(*°▽°*)╯╰(*°▽°*)╯╰(*°▽°*)╯完╰(*°▽°*)╯╰(*°▽°*)╯╰(*°▽°*)╯╰(*°▽°*)╯╰(*°▽°*)╯

你可能感兴趣的:(力扣刷题---,(c语言解题),leetcode,算法,职场和发展,c语言)