题目:
Validate if a given string is numeric.
Some examples:
"0"
=> true
" 0.1 "
=> true
"abc"
=> false
"1 a"
=> false
"2e10"
=> true
Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one.
知识备注:
C/C++ strlen(str)和str.length()和str.size()都可以求字符串长度。
其中str.length()和str.size()是用于求string类对象的成员函数
strlen(str)是用于求字符数组的长度,其参数是char*。
最初思路:检查字符串是否含有字母,如果有并且不是科学计数,返回false,否则返回true.
Attention:注意对科学表示法的判断; 判断".";
不是数字的反例形式太多了,应该从数字正面考虑,其他都返回false.
Error Code: 从非数字的反例出发。
Submission Result: Wrong Answer
Input: | " " |
Output: | true |
Expected: | false |
clas
class Solution {
public:
bool isNumber(const char *s) {
//判断一个字符串是否是表示数字
//思路:检查字符串是否含有字母,如果有并且不是科学计数,返回false,否则返回true.
//Attention:注意对科学表示法的判断; 判断".";
//不是数字的反例形式太多了,应该从数字正面考虑,其他都返回false.
//C/C++ strlen(str)和str.length()和str.size()都可以求字符串长度。
//其中str.length()和str.size()是用于求string类对象的成员函数
//strlen(str)是用于求字符数组的长度,其参数是char*。
for(int i = 0; i < strlen(s); i++)
{
if(isalpha(s[i]))
{
if(s[i] == 'e' || s[i] == 'E' && i >= 1 && ~isdigit(s[i-1]))
{ return false; }
else if(s[i] != 'e' && s[i] != 'E')
{ return false; }
}
else if(s[i] == '.')
{
if(i >= 1 && isdigit(s[i-1]))
{ return true; }
else
{ return false; }
}
}
return true;
}
};
解决问题的有效办法:有限状态机
用有限状态机,非常简洁,不需要复杂的各种判断!
先枚举一下各种合法的输入情况:
1.空格+ 数字 +空格
2.空格+ 点 + 数字 +空格
3.空格+ 符号 + 数字 + 空格
4.空格 + 符号 + 点 + 数字 +空格
5.空格 + (1, 2, 3, 4) + e + (1, 2, 3, 4) +空格
组后合法的字符可以是:
1.数字
2.空格
有限状态机的状态转移过程:
起始为0:初始无输入或者只有space的状态
当输入空格时,状态仍为0,
输入为符号时,状态转为3,3的转换和0是一样的,除了不能再接受符号,故在0的状态的基础上,把接受符号置为-1;
当输入为数字时,状态转为1, 状态1的转换在于无法再接受符号,可以接受空格,数字,点,指数;状态1为合法的结束状态;
当输入为点时,状态转为2,状态2必须再接受数字,接受其他均为非法;
当输入为指数时,非法;
状态1:输入了数字之后的状态
接受数字时仍转为状态1,
接受点时,转为状态4,可以接受空格,数字,指数,状态4为合法的结束状态,
接受指数时,转为状态5,可以接受符号,数字,不能再接受点,因为指数必须为整数,而且必须再接受数字;
状态2:前面无数字,只输入了Dot的状态
接受数字转为状态4;
状态3:输入了符号状态
和0一样,只是不能接受符号;
状态4:前面有数字和有dot的状态
接受空格,合法接受;
接受数字,仍为状态4;
接受指数,转为状态5,
状态5:'e' or 'E'输入后的状态
接受符号,转为状态6,状态6和状态5一样,只是不能再接受符号,
接受数字,转为状态7,状态7只能接受空格或数字;状态7为合法的结束状态;
状态6:输入e之后输入Sign的状态
只能接受数字,转为状态7;
状态7:输入e后输入数字的状态
接受空格,转为状态8,状态7为合法的结束状态;
接受数字,仍为状态7;
状态8:前面有有效数输入之后,输入space的状态
接受空格,转为状态8,状态8为合法的结束状态;
Atttention: 注意状态转移里定义-1即为不合法的输入,停在某些状态即为合法状态。这两点的处理要记住。AC Code:
class Solution {
public:
bool isNumber(const char *s) {
//ERROR 用法 枚举类型书写!!
/* enum InputType
{
INVALID;
SPACE;
SIGN;
DIGIT;
DOT;
EXPONENT;
NUM_INPUT;
}; */
//正确用法,用逗号间隔,最后一个无符号结尾
enum InputType
{
INVALID, // 0
SPACE, // 1
SIGN, // 2
DIGIT, // 3
DOT, // 4
EXPONENT, // 5
NUM_INPUTS // 6
};
int transitionTable[][NUM_INPUTS]
{
-1, 0, 3, 1, 2, -1, // next states for state 0
-1, 8, -1, 1, 4, 5, // next states for state 1
-1, -1, -1, 4, -1, -1, // next states for state 2
-1, -1, -1, 1, 2, -1, // next states for state 3
-1, 8, -1, 4, -1, 5, // next states for state 4
-1, -1, 6, 7, -1, -1, // next states for state 5
-1, -1, -1, 7, -1, -1, // next states for state 6
-1, 8, -1, 7, -1, -1, // next states for state 7
-1, 8, -1, -1, -1, -1, // next states for state 8
};
int state = 0;
while(*s != '\0')
{
InputType inputType = INVALID;
if(isspace(*s))
inputType = SPACE;
else if(*s == '+' || *s == '-')
inputType = SIGN;
else if(isdigit(*s))
inputType = DIGIT;
else if(*s == '.')
inputType = DOT;
else if(*s == 'e' || *s == 'E')
inputType = EXPONENT;
state = transitionTable[state][inputType];
if(state == -1)
return false;
else
++s;
}
return state == 1 || state == 4 || state == 7 || state == 8;
}
};