【剑指offer】63.把字符串转换成整数(atoi)
总目录:
1.问题描述
写一个函数 StrToInt,实现把字符串转换成整数这个功能。不能使用 atoi 或者其他类似的库函数。传入的字符串可能有以下部分组成:
1.若干空格
2.(可选)一个符号字符('+' 或 '-')
3. 数字,字母,符号,空格组成的字符串表达式
4. 若干空格
转换算法如下:
1.去掉无用的前导空格
2.第一个非空字符为+或者-号时,作为该整数的正负号,如果没有符号,默认为正数
3.判断整数的有效部分:
3.1 确定符号位之后,与之后面尽可能多的连续数字组合起来成为有效整数数字,如果没有有效的整数部分,那么直接返回0
3.2 将字符串前面的整数部分取出,后面可能会存在存在多余的字符(字母,符号,空格等),这些字符可以被忽略,它们对于函数不应该造成影响
3.3 整数超过 32 位有符号整数范围 [−2^31, 2^31 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −2^31的整数应该被调整为 −2^31 ,大于 2^31 − 1 的整数应该被调整为 2^31 − 1
4.去掉无用的后导空格
1.去掉无用的前导空格
2.第一个非空字符为+或者-号时,作为该整数的正负号,如果没有符号,默认为正数
3.判断整数的有效部分:
3.1 确定符号位之后,与之后面尽可能多的连续数字组合起来成为有效整数数字,如果没有有效的整数部分,那么直接返回0
3.2 将字符串前面的整数部分取出,后面可能会存在存在多余的字符(字母,符号,空格等),这些字符可以被忽略,它们对于函数不应该造成影响
3.3 整数超过 32 位有符号整数范围 [−2^31, 2^31 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −2^31的整数应该被调整为 −2^31 ,大于 2^31 − 1 的整数应该被调整为 2^31 − 1
4.去掉无用的后导空格
2.问题分析
按规则遍历字符,需要作以下安排
1准备一个状态机用来标记是否处于持续的处理数字过程中
先遍历搜寻正负号或第一个数字,如果遇到正负号则记录下来正负标志位、如果遇到数字则标记位为默认正,然后将开始数字处理的标志位置位,接下来如果遇到非数字字符则停止处理并返回。
2处理数据越界问题
每次遇到新的数字都需要ret=ret*10+newNum,这过程中可能造成数据溢出,对于负数而言在计算之前需要判断ret与int_min/10的关系、ret*10+newNum与int_min的关系,正数同理
3.代码实例

1 class Solution { 2 public: 3 bool isCalcing = false; 4 int pnFlag = 1; 5 const char space = ' ', posFlag = '+', negFlag = '-'; 6 int StrToInt(string s) { 7 int strLen = s.length(); 8 int ret = 0; 9 for (int i = 0; i < strLen; i++) { 10 //如果还在处理开头中 11 if (!isCalcing) { 12 if (s[i] == space) continue; 13 if (s[i] == posFlag) { 14 pnFlag = 1; 15 isCalcing = true; 16 continue; 17 } 18 if (s[i] == negFlag) { 19 pnFlag = -1; 20 isCalcing = true; 21 continue; 22 } 23 } 24 25 //计算中遇到非法数字 26 if (s[i] < '0' || s[i] > '9') { 27 break; 28 } 29 isCalcing = true; 30 31 //处理越界 32 if (ret > INT_MAX / 10 33 || (ret == INT_MAX / 10 && (s[i] - '0') > INT_MAX % 10)) 34 return INT_MAX; 35 if (ret < INT_MIN / 10 36 || (ret == INT_MIN / 10 && (s[i] - '0') > -(INT_MIN % 10))) 37 return INT_MIN; 38 ret = ret * 10 + pnFlag * (s[i] - '0'); 39 } 40 41 return ret; 42 } 43 };