剑指 Offer 20. 表示数值的字符串
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。
数值(按顺序)可以分成以下几个部分:
若干空格
一个 小数 或者 整数
(可选)一个 ‘e’ 或 ‘E’ ,后面跟着一个 整数
若干空格
小数(按顺序)可以分成以下几个部分:
(可选)一个符号字符(’+’ 或 ‘-’)
下述格式之一:
至少一位数字,后面跟着一个点 ‘.’
至少一位数字,后面跟着一个点 ‘.’ ,后面再跟着至少一位数字
一个点 ‘.’ ,后面跟着至少一位数字
整数(按顺序)可以分成以下几个部分:
(可选)一个符号字符(’+’ 或 ‘-’)
至少一位数字
部分数值列举如下:
["+100", “5e2”, “-123”, “3.1416”, “-1E-16”, “0123”]
部分非数值列举如下:
[“12e”, “1a3.14”, “1.2.3”, “±5”, “12e+5.4”]
代码
分类讨论
class Solution {
public:
bool isNumber(string s) {
int i =0,j = s.size()-1;
while(i<=j && s[i] == ' ') i++;
while(i<=j && s[j] == ' ') j--;
s = s.substr(i, j-i+1);
// cout<<s<<endl;
if(s[0]=='+' || s[0]=='-') s = s.substr(1);
if(s.empty() || s[0]=='.' && s.size()==1) return false;
int dot=0, e=0, num=0;
for(int i=0; i<s.size(); ++i){
if(s[i]>='0'&&s[i]<='9'){ //标记遇到了数字
num = 1;
}
else if(s[i] == '.'){ //如果是 '.' 则只能有一个点(e/E前面可以有),如果e/E后面出现点一定错
dot++;
if(dot>1 || e>0) return false;
}
else if(s[i] == 'e' || s[i]=='E'){ //如果是e
e++;
if(e>1 || dot>0 && i==1 || num==0) return false; //只能有一个e/E,如果一个点就错
//e前面没有数也是不正确
if(i+1>=s.size()) return false; //如果e/E是最后一位也是不正确
if(s[i+1]=='+' || s[i+1]=='-'){ //如果e/E后面是+/-
if(i+2 == s.size()) return false; //如果+/-是最后一位不正确
i++; //跳过+/-
}
}
else return false; //其他符号就不正常
}
return true; //true
}
};