如何把一个字符串转换成整数

剑指offer第一章的例子,据说是微软的面试题,发现自己又躺枪了。字符串处理有多烦人不用我多说了吧。

//基础版代码
int StrToInt(char* string)
{ 
	int number = 0;
	while (*string != 0){ 
		number = number * 10 + *string - '0';
		++string;
	}
	return number;
}

需要考虑的特殊情况有:
1.输入字符串有非数字字符正负号
2.考虑到最大整数和最小的负整数以及溢出;
3.考虑到当输入字符串不能转换为整数时该如何进行错误提示;
4.有空白字符应该跳过;

这与LeetCode上的一道题是一样的:

请你来实现一个 atoi 函数,使其能将字符串转换成整数。
首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。

当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。

该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。

注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。

在任何情况下,若函数不能进行有效的转换时,请返回 0。

说明:
假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,请返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。

代码如下:

int myAtoi(string str){ 
    bool negative = false; //适用于没出现正负号默认为正数的情况;
    int index = 0; //索引;
    long long result = 0;
    
    while (index < str.size() && str[index] == ' '){ 
        index++;
    } //指向第一个非空格字符;
    
    if (index == str.size()){  //字符串全部为空字符
        return 0;
    }
    
    if (str[index] == '-'){  //正负号判定;
        negative = true;
        index++;
    }
    else if (str[index] == '+'){ 
        negative = false;
        index++;
    }

    while (index < str.size() && isdigit(str[index])){  //没有到字符串尾且仍然是数字;
        result = result * 10 + str[index++] - '0';
        if (result >= 2147483648){  //int溢出判定;
            if (negative) return INT_MIN;
            else return INT_MAX;
        }
    }
    return negative ? result * (-1) : result; //根据flag negative决定返回的是整数还是负数;
}

这不禁让我想起了LeetCode里的一道类似的题

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串”+100″、“5e2”、”-123″、“3.1416”、“0123″及”-1E-16″都表示数值,但”12e”、“1a3.14”、“1.2.3”、”±5″及”12e+5.4″都不是。

唯一的区别是这道题里包括了小数和科学计数法,并且只需要判断字符串表示的是不是数值,而不需要真正的返回一个数值,所以可以省去溢出判定的步骤。

这类问题大概是三个思路:

  1. 根据编译原理中DFA的知识,画出状态转移表,再使用表驱动的方法,来判断是否可以从字符串中接受到合法的数值(整数和小数)。通常来说,构造DFA的一般流程是:先写出句型的正规表达式,再根据正规表达式画出NDFA,最后进行NDFA的确定化,画出状态转移表。但是这个过程比较繁琐,我花了大半晚上重温了一下编译原理心态爆找。不过这个自动机也比较简单,所以看LeetCode上的题解大家往往表示要啥自行车直接手撸DFA,然后再画出状态转移表。此处可以参考这个题解:表驱动法
  2. 字符串匹配的问题,很难不想到正则表达式。
    根据题意写出符合格式的正则表达式为:’^[\+\-]?(\d+.\d+|.\d+|\d+.|\d+)(e[\+\-]?\d+)?$’;
    C++可以使用regex库,Python可以使用re库,在原字符串中进行模式匹配即可。
  3. 最常见的思路就是根据特征来进行判定,一般是从头到尾扫描,判断是否符合条件。如果成功扫描结束则返回True,如果中途有违反条件的地方则返回True;
    代码:
class Solution { 
public:
    bool isNumber(string &s) 
    { 
        int i = 0;

        //skip the whilespace;
        for (; s[i] == ' '; i++);

        //check the sign if exist;
        if (s[i] == '+' || s[i] == '-') i++;

        //a trick
        int n_nm, n_pt;
        for (n_nm = 0, n_pt = 0; isdigit(s[i]) || s[i] == '.'; i++){ 
            s[i] == '.' ? n_pt++ : n_nm++;
        }
        if (n_pt > 1 || n_nm < 1) return false;

        //check the exponent if exist
        if (s[i] == 'e'){ 
            i++;
            if (s[i] == '+' || s[i] == '-') i++;

            int n_nm = 0;
            for (; isdigit(s[i]); i++, n_nm++);
            if (n_nm < 1) return false;
        }

        //skip the trailing whitespaces
        for (; s[i] == ' '; i++);

        return s[i] == 0;
    }
};
    原文作者:Xiami2019
    原文地址: https://blog.csdn.net/weixin_38742280/article/details/104505319
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞