Valid Number
Validate if a given string is numeric.
Example
"0" => true
" 0.1 " => true
"abc" => false
"1 a" => false
"2e10" => true
Example Questions Candidate Might Ask:
- Q: How to account for whitespaces in the string?
- A: When deciding if a string is numeric, ignore both leading and trailing whitespaces.
- Q: Should I ignore spaces in between numbers – such as “1 1”?
- A: No, only ignore leading and trailing whitespaces. “1 1” is not numeric.
- Q: If the string contains additional characters after a number, is it considered valid?
- A: No. If the string contains any non-numeric characters (excluding whitespaces and decimal point), it is not numeric.
- Q: Is it valid if a plus or minus sign appear before the number?
- A: Yes. “+1” and “-1” are both numeric.
- Q: Should I consider only numbers in decimal? How about numbers in other bases such as hexadecimal (0xFF)?
- A: Only consider decimal numbers. “0xFF” is not numeric.
- Q: Should I consider exponent such as “1e10” as numeric?
- A: No. But feel free to work on the challenge that takes exponent into consideration. (The Online Judge problem does take exponent into account.)
Discussion
一定要澄清问题。通过一个比较全面的例子来分析,“ -2.354 ”有三部分组成ABC, A和C都是whitespace(不单单是空格,isspace()
函数判断),B是数字部分,又有四部分组成B1B2B3B4,B1和B3是符号和小数点是可选的,B2和B4是纯数字部分,不能都为空(因此需要一个indicator来判断两部分是不是都为空)。下面的代码是将B2和B4放一起来判断的,只要小数点不超过1一个就行。如果分开判断的话可以处理上面问题里最后一种情况。
Solution
class Solution {
public:
/**
* @param s the string that represents a number
* @return whether the string is a valid number
*/
bool isNumber(string& s) {
// Write your code here
int i = 0;
int n = s.length();
while(i<n && isspace(s[i])) i++; //A
if( i<n && (s[i] == '+' || s[i] == '-')) i++; //B1
int dotcnt = 0;
bool hasDigit = false;
while (i<n && !isspace(s[i])) {//B2B3B4
if (s[i] == '.') {
dotcnt++;
if(dotcnt >1) //有超过一个小数点的话就false了
return false;
} else if (s[i] < '0' || s[i] >'9') {
return false;
} else {
hasDigit = true; //标注B2B4至少有一个存在
}
i++;
}
while(i<n) { //PART C
if(isspace(s[i]) == false) {
return false;
}
i++;
}
return hasDigit;
}
};
分开处理的solution,方便扩展考虑科学计数法的情况。
class Solution { public: /** * @param s the string that represents a number * @return whether the string is a valid number */ bool isNumber(string& s) { // Write your code here int i = 0; int n = s.length(); while(i<n && isspace(s[i])) i++;// PART A if( i<n && (s[i] == '+' || s[i] == '-')) i++; //B1 int dotcnt = 0; bool hasDigit = false; while (i<n && isdigit(s[i])) { //B2 hasDigit = true; i++; } if(i< n && s[i] == '.') i++; //B3 while (i<n && isdigit(s[i])) { //B4 hasDigit = true; i++; } while(i<n) { //C if(isspace(s[i]) == false) { return false; } i++; } return hasDigit; } };
Update
上面搞的太复杂了,先去掉首尾字符,接下来出现的字符只能是数字/e/./+-/四种里面的一种,分析每一种出现的时候该怎么判断就行了。
class Solution {
public:
/**
* @param s the string that represents a number
* @return whether the string is a valid number
*/
bool isNumber(string& s) {
if(s.length() ==0) return false;
//trim the leading and trailing spaces if any
int i=0;
while(isspace(s[i])) {
i++;
}
s.erase(s.begin(), s.begin()+i);
if(s.length() == 0) return false;
i = s.length()-1;
while(isspace(s[i])) {
s.pop_back();
}
if(s.length() == 0) return false;
//start chcking, 3 cases
//1. number
//2. sign, + -
//3. e --- 1e-10
//4. . -- 0.2
//some examples: 0.1 -0.1, +3.2e+10
bool num = false;
bool sign = false;
bool exp = false;
bool dot = false;
for(int i=0; i<s.length(); i++) {//check each char in s
char c = s[i];
if(isdigit(c)) {
num = true;
} else if(c == '+' || c == '-') {
sign = true;
//sign can be only at 0 or after 'e'
if(i !=0 && s[i-1] !='e') {
return false;
}
} else if(c == 'e') {
//only can be one 'e', and there must be some number before e
if(num==false || exp == true) {
return false;
}
exp = true;
num = false; //make sure there must be some digit after e
} else if(c == '.') {
//at most one '.'
if(dot) {
return false;
}
dot = true;
} else {
return false;
}
}
return num; //not direct true
}
};