题目描述很简单,判断一个数是否为正确数字的格式,如下:
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.
Hint:
1. 指数符号有“e”和“E”。
2. 前后空格不会影响数字,但中间空格会。
3. 如果小数点前没有数字,但是后面有,其实也是数字。同理后面也一样。
4. 比较容易想到的方法是按顺序判断。
一般大多数人(包括我自己)都会想到按顺序判断,即一步步判断每一个符号,如果不符合要求就return false。这样的话就会调用很多个ifor和if语句,造成代码紊乱且不易于阅读。更重要的是,这样很容易会疏漏一些特殊情况,于是就会这边加几个if那边加几个if,纯粹靠的是随即输入时的运气。
这里比较推荐standard answer的做法,先不废话,show the code:
- #include<string>
- enumInput {
- INVALID,// 0, 无效输入
- SPACE,// 1, 空格
- SIGN,// 2, 符号
- DIGIT,// 3, 数字
- DOT,// 4, 小数点
- EXPONENT// 5, 指数
- };
- enumState {
- START,// 0,开始状态,可输入空格、数字、符号、小数点。
- SIGNS,// 1,输入一个符号后的状态。
- DOTFIRST,// 2,小数点前无数字
- DIGITS,// 3, 输入数字
- DOTS,// 4, 小数点后数字
- EXP,// 5, 指数输入
- EXPDIGIT,// 6, 指数
- EXPSIGN,// 7, 指数符号
- END// 8, 后面的多余空格
- };
- bool isNumber(std::string s) {
- int transTable[][6]= {
- -1,0, 1, 3,2, -1,
- -1,-1,-1,3, 2, -1,
- -1,-1,-1,4, -1,-1,
- -1,8, -1,3, 4, 5,
- -1,8, -1,4, -1,5,
- -1,-1,7, 6, -1,-1,
- -1,8, -1,6, -1,-1,
- -1,-1,-1,6, -1,-1,
- -1,8, -1,-1,-1,-1
- };
- int state= 0;
- Input input= INVALID;
- int length= s.length();
- for(int i= 0; i< length; i++){
- char temp= s[i];
- if(temp ==' ') {
- input= SPACE;
- }else if(temp =='+' || temp== '-'){
- input= SIGN;
- }else if(temp >='0'&& temp <='9'){
- input= DIGIT;
- }elseif (temp== '.'){
- input= DOT;
- }else if(temp =='e' || temp== 'E'){
- input= EXPONENT;
- }else if(temp =='+' || temp== '-'){
- input= SIGN;
- }else {
- input= INVALID;
- }
- state= transTable[state][input];
- if(state ==-1){
- returnfalse;
- }
- }
- return state== 3|| state ==4 || state== 6|| state ==8;
- }
该算法最大的魅力之处使用了两个枚举类型enum,没有显式定义内部的顺序则默认为0,1,2……第一个枚举类型为Input表示的是输入字符串的过程中没按下键盘上的键,即输入每一个字符char的时候,改变当前的Input类型,之后通过一个
“状态机”概念的table来改变当前整个字符串的state状态,再判断该state,将整个字符串的每个字符都遍历一遍之后就可以判断该数字是否是valid的了。
这里提出一个概念,<状态机>
状态机也叫有限状态机,英文名为FSM,它是编程中的一个重要概念。通俗的说,就是本在状态A下,触发了一个键之后就切换到了状态B,再触发另一个键之后就到了状态C,这就是个简单的状态机例子,真正复杂的状态机应用是在单片机上面。其实我们编写的程序也算是一种状态机,一个if,一个for,一个return都从一个状态转变到另外一个状态。状态机的要素有四个要点,第一是现态,顾名思义是现在的状态。第二是条件,用于判断。第三是动作,用于转换另外一个状态时所需要的代码,第四是次态,次态其实就是结果,转换成另一个状态的结果。而一个应用状态机的编程理应具备这四个条件。
上述题目中,Input就是一个动作,State就是现态和次态。而其中的if和else语句是判断。而存放现态和次态的是一个二维数组的table,一个Input的触发则导致矩阵的位置的变化,而不同行数对应的是不同的状态,而列数则是下一步可以到达的状态,这样一个状态机式的编程就出来了。既简洁编码量又不至于过长。
最后,分享一个关于状态机的基本概念和编程思想的网址
http://wenku.baidu.com/link?url=pO1rSETivIohJbQg7OnXB8JwDzW2_3xFPGHdmLhl-kiI_XfOzcVb06EOiYlUYzfjE002Tl5veEvKB42PqqmJSEnFZ4Sz6njhQhcREzZLacO