请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。
方法零
根据正则表达式:[\\+-]?[0-9]*(\\.[0-9]*)?([eE][\\+-]?[0-9]+)?,可以写出下面的代码
这段代码牛逼的地方在于搞了个全局的bool值作为状态迁移的一依据
class Solution {
void check(char *&s, bool &res) {
while (isdigit(*s)) {
++s;
res = true;
}
}
public:
bool isNumeric(char* s) {
if (!s) return false;
if (*s == '-' || *s == '+') ++s;
bool res = false;
check(s, res);
if (*s == '.') check(++s, res);
if (res & (*s == 'e' || *s == 'E')) {
++s;
res = false;
if (*s == '-' || *s == '+') ++s;
check(s, res);
}
return res && *s == '\0';
}
};
方法一
状态迁移表实现 :
class Solution {
public:
char arr[10] = "+-n.ne+-n";
int turn[10][9] = {
//+ - n . n e + - n
{1, 1, 1, 0, 0, 0, 0, 0, 0}, // # start
{0, 0, 1, 1, 0, 0, 0, 0, 0}, // +
{0, 0, 1, 1, 0, 0, 0, 0, 0}, // -
{0, 0, 1, 1, 0, 1, 0, 0, 0}, // n
{0, 0, 0, 0, 1, 0, 0, 0, 0}, // .
{0, 0, 0, 0, 1, 1, 0, 0, 0}, // n
{0, 0, 0, 0, 0, 0, 1, 1, 1}, // e
{0, 0, 0, 0, 0, 0, 0, 0, 1}, // +
{0, 0, 0, 0, 0, 0, 0, 0, 1}, // -
{0, 0, 0, 0, 0, 0, 0, 0, 1} // n
};
bool isNumeric(char* string) {
int cur = 0;
for(int j, i = 0; string[i]; i++) {
for(j = 0; j < 9; j++) {
if(turn[cur][j]) {
if(('0' <= string[i] && string[i] <= '9' && arr[j] == 'n') ||
(string[i] == 'E' && arr[j] == 'e')||
string[i] == arr[j]) {
cur = j + 1;
break;
}
}
}
if(j == 9) return false;
}
if(cur == 3 || cur == 4 || cur == 5 || cur == 9)
return true;
return false;
}
};
关键是搞清楚这个表是什么意思:
int turn[10][9] = {
//+ - n . n e + - n
{1, 1, 1, 0, 0, 0, 0, 0, 0}, // # start
{0, 0, 1, 1, 0, 0, 0, 0, 0}, // +
{0, 0, 1, 1, 0, 0, 0, 0, 0}, // -
{0, 0, 1, 1, 0, 1, 0, 0, 0}, // n
{0, 0, 0, 0, 1, 0, 0, 0, 0}, // .
{0, 0, 0, 0, 1, 1, 0, 0, 0}, // n
{0, 0, 0, 0, 0, 0, 1, 1, 1}, // e
{0, 0, 0, 0, 0, 0, 0, 0, 1}, // +
{0, 0, 0, 0, 0, 0, 0, 0, 1}, // -
{0, 0, 0, 0, 0, 0, 0, 0, 1} // n
};
第0行(# start)代表第一个字符可以匹配的有+,-,n;
第1、2(+,-)行分别代表+,-后面可以匹配的字符,为 n 或 .
第3行(n)代表n的下一个字符可以匹配的字符,n,.
第4行(.)代表.的下一个字符可以匹配的字符n
...
第9行(n)代表排在e后面的n的下一个字符可以匹配的字符
方法二
链接:https://www.nowcoder.com/questionTerminal/6f8c901d091949a5837e24bb82a731f2
来源:牛客网
class Solution {
private:
enum STATUS{ END = 0, START, SIGNED1, INTEGER, POINT, FLOAT, EXPONENT, SIGNED2, SCIENCE };
STATUS dfa[256][9] = { END };
public:
Solution(){
for (int i = 0; i < 256; ++i)
{
for (int j = 0; j < 9; ++j)
{
dfa[i][j] = END;
}
}
initDFA();
}
bool isNumeric(char* string)
{
STATUS current = START;
while (*string && current != END)
{
current = DFA(current, *string);
++string;
}
switch (current)
{
case INTEGER:
case FLOAT:
case SCIENCE:
return true;
}
return false;
}
private:
void initDFA(){
char d = '0';
// 1. START 变迁
dfa['+'][START] = SIGNED1;
dfa['-'][START] = SIGNED1;
dfa['.'][START] = POINT;
for (d = '0'; d <= '9'; ++d)
{
dfa[d][START] = INTEGER;
}
// 2. SIGNED1 变迁
for (d = '0'; d <= '9'; ++d)
{
dfa[d][SIGNED1] = INTEGER;
}
dfa['.'][SIGNED1] = POINT;
// 3. INTEGER 变迁
for (d = '0'; d <= '9'; ++d)
{
dfa[d][INTEGER] = INTEGER;
}
dfa['.'][INTEGER] = FLOAT;
dfa['E'][INTEGER] = EXPONENT;
dfa['e'][INTEGER] = EXPONENT;
// 4. POINT 变迁
for (d = '0'; d <= '9'; ++d)
{
dfa[d][POINT] = FLOAT;
}
// 5. FLOAT 变迁
for (d = '0'; d <= '9'; ++d)
{
dfa[d][FLOAT] = FLOAT;
}
dfa['E'][FLOAT] = EXPONENT;
dfa['e'][FLOAT] = EXPONENT;
// 6. EXPONENT 变迁
for (d = '0'; d <= '9'; ++d)
{
dfa[d][EXPONENT] = SCIENCE;
}
dfa['+'][EXPONENT] = SIGNED2;
dfa['-'][EXPONENT] = SIGNED2;
// 7. SIGNED2 变迁
for (d = '0'; d <= '9'; ++d)
{
dfa[d][SIGNED2] = SCIENCE;
}
// 8. SCIENCE 变迁
for (d = '0'; d <= '9'; ++d)
{
dfa[d][SCIENCE] = SCIENCE;
}
// 其余情况均变迁到 END
}
STATUS DFA(STATUS current, char input)
{
STATUS ret = START;
return dfa[input][current];
}
};