刚开始首先想到的是用几个状态标志记录如点,符号,E等字符的出现,然后去判断,这样写出来的代码由无数if else构成,难读容易出错并且不好扩展。
看了官方的有限状态机方法,发现非常简洁优雅,逻辑清晰易读,扩展方便。
有限状态机需要构造一个转移矩阵,一旦矩阵构造完,剩下的逻辑代码就非常好写了。
我这里用了10个状态。分别表示以下情况(正则表达式):
0:[space]+
1:(+|-)
2:[+|-]{0,1}\.
3:[+|-]{0,1}[0-9]+
4:[+|-]{0,1}\.[0-9]+
5:[+|-]{0,1}[0-9]+[\.]{0,1}[0-9]+(E|e)
6:[+|-]{0,1}[0-9]+\.
7:[+|-]{0,1}[0-9]+[\.]{0,1}[0-9]+(E|e)(+|-)
8:[+|-]{0,1}[0-9]+[\.]{0,1}[0-9]+(E|e)(+|-)[0-9]+
9:[+|-]{0,1}[0-9]+[\.]{0,1}[0-9]+(E|e)[0-9]+
10:状态3,4,6,8,9 + space
class Solution {
public:
bool isNumber(const char *s) {
enum input_type{
INVALID,
SPACE,
SIGN,
DOT,
DIGIT,
EXP,
NUM
};
int trans[][NUM]={
-1,0,1,2,3,-1,
-1,-1,-1,2,3,-1,
-1,-1,-1,-1,4,-1,
-1,10,-1,6,3,5,
-1,10,-1,-1,4,5,
-1,-1,7,-1,9,-1,
-1,10,-1,-1,4,5,
-1,-1,-1,-1,8,-1,
-1,10,-1,-1,8,-1,
-1,10,-1,-1,9,-1,
-1,10,-1,-1,-1,-1,
};
int state = 0;
while(*s!='\0'){
input_type input = INVALID;
if(*s==' ')
input = SPACE;
else if(*s=='+'||*s=='-')
input = SIGN;
else if(*s == '.')
input = DOT;
else if(isdigit(*s))
input = DIGIT;
else if(*s=='e'||*s=='E')
input = EXP;
state = trans[state][input];
if(state==-1)
return false;
++s;
}
return state==3 || state==4 || state==6 || state==8 || state==9 || state== 10;
}
};