剑指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″都不是。
唯一的区别是这道题里包括了小数和科学计数法,并且只需要判断字符串表示的是不是数值,而不需要真正的返回一个数值,所以可以省去溢出判定的步骤。
这类问题大概是三个思路:
- 根据编译原理中DFA的知识,画出状态转移表,再使用表驱动的方法,来判断是否可以从字符串中接受到合法的数值(整数和小数)。通常来说,构造DFA的一般流程是:先写出句型的正规表达式,再根据正规表达式画出NDFA,最后进行NDFA的确定化,画出状态转移表。但是这个过程比较繁琐,我花了大半晚上重温了一下编译原理心态爆找。不过这个自动机也比较简单,所以看LeetCode上的题解大家往往表示要啥自行车直接手撸DFA,然后再画出状态转移表。此处可以参考这个题解:表驱动法。
- 字符串匹配的问题,很难不想到正则表达式。
根据题意写出符合格式的正则表达式为:’^[\+\-]?(\d+.\d+|.\d+|\d+.|\d+)(e[\+\-]?\d+)?$’;
C++可以使用regex库,Python可以使用re库,在原字符串中进行模式匹配即可。 - 最常见的思路就是根据特征来进行判定,一般是从头到尾扫描,判断是否符合条件。如果成功扫描结束则返回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;
}
};