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.
分析:典型的细节实现题
这个题本身并不难,就和atoi( )函数一样,其实考察的是各种情况考虑是否周全。以下为一些注意事项:
- 前后空白的处理
- 记录第一个非空白且非正负号的位置,这样实现时更方便
- 就算是用指数表示法,其指数部分必须为整数,所以小数点只可能有一个,且其前后必须有数字
- 越界问题,常常被忽略,各种情况下的越界
- 边界问题:e或.是否在首(非空白、非正负号)尾位置
- 真是细节决定成败啊,每次提交,总有遗漏的情况,而且,测试用例自己写的时候,偏重于非法的,以至于合法的情况过少,反而考虑不周,导致出错
1 #include "stdafx.h" 2 #include <string> 3 #include <iostream> 4 //include <ctype.h>//isalnum(),isalpha,isdight() 5 using namespace std; 6 7 inline bool isNum(int x) 8 { 9 if(x>='0' && x<='9') 10 return true; 11 return false; 12 } 13 class Solution 14 { 15 public: 16 bool isNumber(string s) 17 {/* 18 判断输入的字符串是否是数字[难就难在要考虑各种情况] 19 整数、小数、负数、浮点数表示 20 浮点数表示法:小数表示法[整数和小数部分不能同时省略]; 21 指数表示法[指数部分以e或E开始,且必须为整数;e或E两边至少有一位数] 22 有效字符:0~9、+、-、首尾空白、e、E、.、 23 忽略头尾空白 24 25 复数就不考虑了吧。。。3+2i 26 注意:e9不合法!!! 27 特例: 28 false:"+"、"-"、"." 29 */ 30 if(s.size() == 0) 31 return false; 32 33 auto it = s.begin(); 34 while(it != s.end() && (*it) == ' ')//忽略前面的空格,指向第一个非空格位置 35 it++; 36 37 auto iend = s.end()-1;//用于标识最后一个非空格位置后的第一个空格处,即尾后 38 while(iend >= it && (*iend) == ' ') 39 { 40 iend--; 41 } 42 iend++;//iend标识的是。 43 if(it == iend) 44 return false;//只有空格!!!之前漏了 45 46 if(it != iend)//开头为正负号 47 { 48 if((*it) == '+' || (*it) == '-' ) 49 it++; 50 if(it == iend)//仅有正负号,不是数字 51 return false; 52 } 53 auto ibegin = it;//用于标识第一个非空位置 且不是正负号的位置!!! 54 55 bool isFloat = false;//标识是否为指数表示法,即有没有e或E 56 bool isPoint = false;//小数点是否出现 57 //之后,有效字符为./e/E/0~9/+/-(正负号仅允许在e或E之后) 58 while(it != iend) 59 { 60 if(isNum(*it))//是数字,直接判断下一位 61 { 62 it++; 63 continue; 64 } 65 if((*it) == '.')//是小数点 66 {//只可能有一个小数点,因为指数部分必须为整数!!!之前忘了 67 if(isPoint || isFloat)//!!!之前遗漏了 68 return false;//e或E出现了也不可以再出现小数点!!! 69 if(it == ibegin) 70 { 71 if(it+1 == iend)//注意越界判断!!! 72 return false; 73 if(it < iend && !isNum(*(it+1)))//小数点前后必须得有数字!!!.e2 74 return false; 75 } 76 isPoint = true; 77 it++; 78 /* 79 if(it == iend)//这一步没必要了,因为上一个if已经判断了!!! 80 { 81 if((it-1) != ibegin && isNum(*(it-2))) 82 //!!!前面有且有数字才可以,两个条件之前都漏了;而且,是-2,不是-1;(it-1)而不是it 83 return true; 84 else 85 return false;//只有.,不是数字 86 } 87 */ 88 continue; 89 } 90 if((*it) == 'e' || (*it) == 'E') 91 { 92 if(isFloat || it == ibegin) 93 //||!isNum(*(it-1)))//e或E已经出现过!!!之前漏了;ibegin改为包括正负号,就不需要这个条件了 94 //e2不合法哟,所以也要加上是否为第一个非空白字符!!! 95 //若不是第一个非空字符,前一个还必须得是数字,+E2不合法; 96 //得-1呀,亲 97 return false; 98 else 99 isFloat = true; 100 it++; 101 if(it == iend) //要保留,因为后面判断正负号可能存在越界 102 return false;//e后面必须跟数字,所以,与小数点情况是不同的,之前弄错了!! 103 //只有在e后面紧跟着的正负号,且只有一个正负号,才是有效的 104 if((*it) == '+' || (*it) == '-') 105 it++; 106 if(it == iend) 107 return false;//2.3e+,2.3E-不是数字 108 109 continue; 110 } 111 if(1)//如果到达这里,说明不是有效字符 112 return false; 113 } 114 return true; 115 } 116 }; 117 118 119 int main() 120 { 121 Solution sol; 122 // cout<< sol.isNumber(" 46.e3 ")<<endl; 123 string test[] = {string("0"),string(" 0.1 "),string("2e10"),string("-3.4e-2"),string("112345"), 124 string("1.044"),string(" 1.044 "),string("1e2"),string("1."), 125 string(".2"),string("+1."),string(" -1."),string("005047e+6"), 126 string("2e0"),string("46.e3"), 127 string("e2"),//不合法哟 128 string("1.a"),string(" "),string("."),string("1.."),string("6e6.5"), 129 string("abc"),string("1 a") ,string("+"),string("-"),string(" . "), 130 string("2.3.4"),string("e "),string("2.3e+"),string("2.3e-"),string(""), 131 string("ee"),string("+."),string("+e"),string("++e2"),string("1e") 132 }; 133 134 135 //true; 136 //false 137 //还是漏了几种情况:string("1.")、string("1e"),string("+1."),string(" -1."),string("e22e2"),string("-3.2e3.4") 138 //提交错误用例:e2,.e1,+E3,2e0(应该正确),46.e3(应该正确) 139 140 std::cout << boolalpha ; 141 for(auto const &i : test) 142 cout<< i << " : " << sol.isNumber(i)<<endl; 143 144 return 0; 145 }
参考:https://github.com/haoel/leetcode/blob/master/algorithms/validNumber/validNumber.cpp