问题描述
<pre> 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. </pre>
<!--more-->
这道题看上去很简单,但是实际做的时候发现有很多意外的情况,主要是 case 没有想完全,有的 case 甚至是想错了。每次发现意外情况就微调下代码,到最后代码乱得自己都不想看了,而且再改起来牵一发动全身的感觉。于是又稍微重构了一下代码。最后 AC 的代码如下:
public class ValidNumber {
public boolean isNumber(String s) {
String trimed = s.trim();
int len = trimed.length();
boolean isNewGroup = true, hasNumberInGroup = false, hasPointInGroup = false;
int groupNum = 1;
for (int i = 0; i < len; i++) {
char ch = trimed.charAt(i);
if (!validChar(ch)) {
return false;
}
if (isNewGroup) {
isNewGroup = false;
if (isDigit(ch)) {
hasNumberInGroup = true;
} else if (isPoint(ch)) {
if (groupNum > 1) {
return false;
}
hasPointInGroup = true;
} else if (isE(ch)){
return false;
} else {
continue;
}
} else {
if (isSign(ch)) {
return false;
} else if (isPoint(ch)) {
if (hasPointInGroup) {
return false;
} else {
if (groupNum > 1) {
return false;
}
hasPointInGroup = true;
}
} else if(isE(ch)) {
if (!hasNumberInGroup) {
return false;
}
isNewGroup = true;
hasNumberInGroup = false;
hasPointInGroup = false;
groupNum++;
if (groupNum > 2) {
return false;
}
} else {
hasNumberInGroup = true;
continue;
}
}
}
if (!hasNumberInGroup) {
return false;
}
return true;
}
private boolean validChar(char ch) {
return (isSign(ch)
|| isDigit(ch)
|| isE(ch)
|| isPoint(ch));
}
private boolean isSign(char ch) {
return (ch == '-' || ch == '+');
}
private boolean isDigit(char ch) {
return (ch >= '0' && ch <= '9');
}
private boolean isE(char ch) {
return (ch == 'e' || ch == 'E');
}
private boolean isPoint(char ch) {
return ch == '.';
}
}
可以说这段代码写的并不漂亮,勉强能行吧。后来看到网上有人用状态机去做,代码比较清晰。不过我想当他不断遇到意外情况的时候调整状态机,应该也比较费劲吧。
后来给一个同事看这个题,刚开始也跟我感觉一样,觉得应该挺简单的,真正做起来也发现挺坑爹的。