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

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

(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++,跳过这个字符

 

 第二条

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

就是判断正负

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

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

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

代码实现

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

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

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

 

 注意:这里直接用的从上边走下来的  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里的数是截断之后的了,谁知道是什么,更何谈判断,所以这个方法不行我们往下看正确示范🙉🙉

 2.   正确示范🙉🙉🙉🙉

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

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

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

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

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

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

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

 完整代码(带主函数)

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<limits.h>
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;
}

 

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