HomeWork——Valid Number

题目描述很简单,判断一个数是否为正确数字的格式,如下:

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:


  1. #include<string>
  2.  
  3. enumInput {
  4. INVALID,// 0, 无效输入
  5. SPACE,// 1, 空格
  6. SIGN,// 2, 符号
  7. DIGIT,// 3, 数字
  8. DOT,// 4, 小数点
  9. EXPONENT// 5, 指数
  10. };
  11. enumState {
  12. START,// 0,开始状态,可输入空格、数字、符号、小数点。
  13. SIGNS,// 1,输入一个符号后的状态。
  14. DOTFIRST,// 2,小数点前无数字
  15. DIGITS,// 3, 输入数字
  16. DOTS,// 4, 小数点后数字
  17. EXP,// 5, 指数输入
  18. EXPDIGIT,// 6, 指数
  19. EXPSIGN,// 7, 指数符号
  20. END// 8, 后面的多余空格
  21. };
  22. bool isNumber(std::string s) {
  23. int transTable[][6]= {
  24. -1,0, 1, 3,2, -1,
  25. -1,-1,-1,3, 2, -1,
  26. -1,-1,-1,4, -1,-1,
  27. -1,8, -1,3, 4, 5,
  28. -1,8, -1,4, -1,5,
  29. -1,-1,7, 6, -1,-1,
  30. -1,8, -1,6, -1,-1,
  31. -1,-1,-1,6, -1,-1,
  32. -1,8, -1,-1,-1,-1
  33. };
  34. int state= 0;
  35. Input input= INVALID;
  36. int length= s.length();
  37. for(int i= 0; i< length; i++){
  38. char temp= s[i];
  39. if(temp ==' ') {
  40. input= SPACE;
  41. }else if(temp =='+' || temp== '-'){
  42. input= SIGN;
  43. }else if(temp >='0'&& temp <='9'){
  44. input= DIGIT;
  45. }elseif (temp== '.'){
  46. input= DOT;
  47. }else if(temp =='e' || temp== 'E'){
  48. input= EXPONENT;
  49. }else if(temp =='+' || temp== '-'){
  50. input= SIGN;
  51. }else {
  52. input= INVALID;
  53. }
  54. state= transTable[state][input];
  55. if(state ==-1){
  56. returnfalse;
  57. }
  58. }
  59. return state== 3|| state ==4 || state== 6|| state ==8;
  60. }

该算法最大的魅力之处使用了两个枚举类型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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值