判断给出的字符串是否是数字
一些例子:
"0"=>true
" 0.1 "=>true
"abc"=>false
"1 b"=>false
"3e10"=>true
" 0.1 "=>true
"abc"=>false
"1 b"=>false
"3e10"=>true
/* * * 发现解答很多都用了一些小技巧,比如正则,或者NumberFormatException * 实际上这些解法都调用库函数,个人觉得不是出题者的真正意图 * * * Runtime: 3 ms.Your runtime beats 83.72 % of java submissions. * 思路:这道题关键是分析所有会出现的情况。以及设置关键的flag来记录各种情况 * 首先使用trim()函数去除前后空格。 * 设置4个标志,分别是 * boolean pointSeen = false;//是否出现过小数点“.” * boolean eSeen =alse;//是否出现过指数标志“e” * boolean numberSeen = false;//是否出现过数字 * booleannumberAfterE = true;//e后面是否有数字 * 进行循环s.charAt(i): * 1.如果属于[0,9],把numberSeen设为true * 2.如果是‘.’,必须之前没有遇到'.'和'e' * 3.如果是'e',必须之前没有遇到过'e' * 4.如果是'+'或者'-',当前i必须是0,或者i-1上的字符是e * 5.其他情况返回false */ public boolean isNumber(String s) { s = s.trim(); if (s == null || s.length() == 0) return false; // 记录是否出现过数字 boolean numberSeen = false; // 是否出现过小数点 boolean pointSeen = false; // 是否出现过指数标志e boolean eSeen = false; // e后是否出现过数字 boolean numberAfterE = false; for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); // 如果是数字 if (c >= '0' && c <= '9') { numberSeen = true; numberAfterE = true; // 如果是小数点 } else if (c == '.') { if (pointSeen || eSeen) return false; pointSeen = true; // 如果是e,必须没有出现过且出现过数字 } else if (c == 'e') { if (eSeen || !numberSeen) return false; eSeen = true; numberAfterE = false; // 如果出现正负号,必须是首位,或者前一位是e } else if (c == '+' || c == '-') { if (i != 0 && s.charAt(i - 1) != 'e') return false; } else return false; } return numberSeen && numberAfterE; }
class Solution { public: bool isNumber(const char *s) { string str(s); int k = str.find_first_not_of(' '); if(str[k]=='+' || str[k]=='-') k++; int p=0, num1=0; for(;str[k]>='0' && str[k]<='9' || str[k]=='.';k++) s[k] == '.'?p++:num1++; if(p>1 || num1<1) return false; if(str[k] == 'e' || str[k]=='E') { k++; if(str[k] == '+' || str[k]=='-') k++; int num2 = 0; for(;str[k]>='0' && str[k]<='9';k++) num2++; if(num2==0) return false; } for(;str[k]==' ';k++); return str[k]=='\0'; } };
public boolean isNumber(String s) { return s.matches("(\\s)*([+-])?(([0-9]*\\.)?([0-9]+)|([0-9]+)(\\.[0-9]*)?)([eE][\\+-]?[0-9]+)?(\\s)*"); }
class Solution { public: bool isNumber(const char *s) { int n=strlen(s); if(s==NULL) return false; if(n==1&&s[0]==' ')//情形为“ ” return false; if(n==1&&s[0]=='.')//情形为“.” return false; if(n==1&&(s[0]=='e'||s[0]=='E'))//情形为“e” return false; bool ee=false;//是否出现过‘e’ bool point=false;//是否出现过. bool nums=false;//是否出现过数字 bool mark=false;//在e前出现的正负号 bool mark1=false;//在e后出现的正负号 int i=0; while(s[i]!='\0'){ if(s[i]=='-'||s[i]=='+'||s[i]=='e'||s[i]=='E'||s[i]=='.'||(s[i]>='0'&&s[i]<='9')||s[i]==' '){ if(s[i]=='-'||s[i]=='+'){ if(ee==true){//如果实在e后出现的正负号 if(mark1==false){ mark1=true; int j=i+1; if(j>=n||!(s[j]>='0'&&s[j]<='9'))//e+/e- return false; } else return false;//e后正负号多次出现 } else{//e前出现的正负号 if(nums==true||point==true)//8+/.+ return false; else{ if(mark==true)//如果e前正负号出现多次 return false; else mark=true; } } } if(s[i]==' '){ if(nums==false&&ee==false&&point==false&&mark==false); else{//如果在中间位置出现‘ ’ int j=i+1; while(j<n){ if(s[j]!=' ') return false; j++; } } } if(s[i]=='.'){ if(ee==false){ if(point==false){ point=true; } else//e前出现多个小数点 return false; } else//e后出现多个小数点 return false; } if(s[i]=='E'||s[i]=='e'){ if(ee==false){ if(i==n-1||(nums==false&&point==false)||(nums==false&&point==true)) return false;//e后出现小数点/e前没有任何信息 else ee=true; } else return false; int j=i+1; while(j<n){ if(s[j]==' ') j++; else break; } if(j>=n)//e后没有数字 return false; } if(s[i]>='0'&&s[i]<='9') nums=true; i++; } else return false; } if(nums==false&&point==true)//如果没有数字只有小数点 return false; return true; } };
// 亲测本机上没问题,提交却显示错误,难道是因为我用的是Java8? public class Solution { public boolean isNumber(String s) { if (s.charAt(s.length()-1) > '9' || s.charAt(s.length()-1) < '0') return false; try { Double.valueOf(s); } catch (Exception e) { return false; } return true; } }
class Solution { public: bool isNumber(const char *s) { string str(s); int index = str.find_first_not_of(' '); if(str[index] == '+' || str[index] == '-') index++; int points = 0,numbers = 0; for(;str[index]>='0' && str[index]<='9' || str[index]=='.';index++) s[index] == '.' ? ++points : ++ numbers; if(points>1 || numbers<1) return false; if(str[index] == 'e' || str[index] == 'E') { index++; if(str[index] == '+' || str[index] == '-') index++; int afterE =0; for(;str[index]>='0' && str[index]<='9';index++) afterE++; if(afterE<1) return false; } for(;str[index]==' ';index++){} return str[index]=='\0'; } };
public class Solution { public boolean isNumber(String s) { try { Double valueOf = Double.valueOf(s); //排除Double类对特殊的末尾字符为F(f)或D(d)的处理,其他如果不是数字类型,则catch! if(s.indexOf("f")>-1 || s.indexOf("F")>-1 || s.indexOf("d")>-1 || s.indexOf("D")>-1){ return false; } return true; } catch (Exception e) { return false; } } }
class Solution { public: bool isNumber(const char *s) { enum InputType { INVALID, SPACE, SIGN, DOT, E, DIGIT, LEN }; int trans[][LEN] = { {-1, 0, 1, 2, -1, 3}, {-1, -1, -1, 2, -1, 3}, {-1, -1, -1, -1, -1, 4}, {-1, 5, -1, 4, 6, 3}, {-1, 5, -1, -1, 6, 4}, {-1, 5, -1, -1, -1, -1}, {-1, -1, 7, -1, -1, 8}, {-1, -1, -1, -1, -1, 8}, {-1, 5, -1, -1, -1, 8} }; int state = 0; while (*s) { InputType input; if (isspace(*s)) { input = SPACE; } else if (*s == '+' || *s == '-') { input = SIGN; } else if (*s == '.') { input = DOT; } else if (*s == 'e' || *s == 'E') { input = E; } else if (isdigit(*s)) { input = DIGIT; } else { input = INVALID; } state = trans[state][input]; if (state == -1) { return false; } s++; } return state == 3 || state == 4 || state == 5 || state == 8; } };
class Solution { public: bool isNumber(const char *str) { int zhuang[9][6]={{-1,0,1,2,-1,3}, {-1,-1,-1,2,-1,3}, {-1,-1,-1,-1,-1,4}, {-1,5,-1,4,6,3}, {-1,5,-1,-1,6,4}, {-1,5,-1,-1,-1,-1}, {-1,-1,7,-1,-1,8}, {-1,-1,-1,-1,-1,8}, {-1,5,-1,-1,-1,8}},i,zhuangtai=0,jieshou; for(i=0;str[i]!='\0';i++) { if(str[i]==' ') jieshou=1; else if(str[i]=='.') jieshou=3; else if('0'<=str[i]&&str[i]<='9') jieshou=5; else if(str[i]=='+'||str[i]=='-') jieshou=2; else if(str[i]=='e') jieshou=4; else jieshou=0; zhuangtai=zhuang[zhuangtai][jieshou]; if(zhuangtai==-1) return false; } if(zhuangtai==3||zhuangtai==4||zhuangtai==5||zhuangtai==8) return true; else return false; } };
这道题目有点类似于atoi
(将字符串转化为整数),回想一下atoi
:如果第一个非空格字符不存在或者不是数字也不是正负号则返回零,否则开始做类型转换,之后检测到非数字(包括结束符 \0) 字符时停止转换,返回整型数。
这道题目里面我们采取以下步骤:
如果是科学计数法,需要符合:
具体的实现方案:
help
函数,它会返回三个可能的值,0表示非数字,1表示整数,2表示小数 代码如下:
// // Created by jt on 2020/9/26. // class Solution { public: bool isNumber(const char *s) { // 判断是否含有e const char *p = s; while (*p) { if (*p == 'e') break; ++p; } if (*p) { // 如果含有e,先判断e的前后是否有空格 if (p-1 >= s && *(p-1) != ' ' && *(p+1) && *(p+1) != ' ') return help(s, p) > 0 && help(p+1, nullptr) == 1; else return false; } return help(s, nullptr) > 0; } int help(const char *s, const char *end) { // 返回0表示非数字 返回1表示整数 返回2表示小数 if (s == end) return 0; // 忽略前置空格 while (*s == ' ') ++s; // 如果只有空格 if (!(*s)) return 0; // 记录正负号和句点 bool hasSign = false, hasDot = false, hasNum = false; if (*s == '+' || *s == '-') { hasSign = true; ++s; } while (*s && *s != ' ' && s != end) { if (hasSign && (*s == '+' || *s == '-')) return 0; if (hasDot && *s == '.') return 0; if (*s == '.') { hasDot = true; ++s; continue; } if (*s < '0' || *s > '9') return 0; hasNum = true; ++s; } // 忽略后置空格 while (*s && s != end) { if (*s != ' ') return 0; ++s; } if (hasNum && !hasDot) return 1; if (hasNum && hasDot) return 2; return 0; } };
class Solution { public: bool isNumber(const char *s) { int i,start=1,a[2]={0,0},loc[2]={0,0},k1=0,k2=0; vector<int>n; if(s=="") return false; for(i=0;i<strlen(s);i++) { if(s[i]!=' ') { start=i+1; break; } } if(s[start-1]=='+'||s[start-1]=='-') { start++; n.push_back(0); } for(i=start-1;i<strlen(s);i++) { if(s[i]<'0'||s[i]>'9') { if(s[i]=='.') { if(i!=strlen(s)-1&&(s[i+1]>'9'||s[i+1]<'0')&&s[i+1]!=' ') if(s[i+1]!='e'&&s[i+1]!='E') return false; else if(k2==0) return false; a[0]++; loc[0]=i+1; n.push_back(0); } else if(s[i]=='e'||s[i]=='E') { if(i==strlen(s)-1) return false; else if(s[i+1]>'9'||s[i+1]<'0') if(s[i+1]!='+'&&s[i+1]!='-') return false; else if(i+1==strlen(s)) return false; else if(s[i+2]>'9'||s[i+2]<'0') return false; a[1]++; loc[1]=i+1; n.push_back(0); } else if(s[i]=='+'||s[i]=='-') if(s[i-1]!='e'&&s[i-1]!='E') return false; else ; else if(s[i]==' ') n.push_back(1); else return false; } else { n.push_back(0); k2=1; } } if(k2==0) return false; if(a[0]>1||a[1]>1) return false; if(loc[0]>loc[1]&&loc[1]!=0) return false; if(start==loc[1]) return false; for(i=0;i<n.size();i++) { if(n[i]==0) if(k1==0||k1==1) k1=1; else return false; else if(k1==1) k1=2; } if(k1==0) return false; return true; } };太多陷阱了。。。。眼睛快瞎了,用最笨的办法,今天不想改进了
/* * 目的:判断一个字符是否是数字 * 参考:剑指offer-20 */ bool scanUInt(const char**str){ const char* before = *str; while(**str!='\0' && **str>='0' && **str<='9') ++(*str); return *str>before; } bool scanInt(const char**str){ while(**str=='+' || **str=='-') ++(*str); return scanUInt(str); } bool isNumber(const char *s) { if (s == nullptr) return false; while(*s==' ') s++; bool numeric = scanInt(&s); if (*s == '.'){ s++; numeric=scanUInt(&s)||numeric; } if (*s == 'e' || *s=='E'){ s++; numeric=numeric&&scanInt(&s); } while(*s==' ') s++; return numeric && *s=='\0'; }
class Solution { public: bool isNumber(const char *s) { bool numberSeen = false; bool eSeen = false; bool numberAfterE = false; bool pointSeen = false; int start = 0; int end = strlen(s) - 1; while (start < strlen(s)) { if (s[start] != ' ') { break; } start++; } while (end >= 0) { if (s[end] != ' ') { break; } end--; } for (int i = start;i <= end;i++) { char c = s[i]; if (c >= '0' && c <= '9') { numberSeen = true; numberAfterE = true; } else if (c == '.') { if (pointSeen || eSeen) { return false; } pointSeen = true; } else if (c == 'e' || c == 'E') { if (eSeen || !numberSeen) { return false; } eSeen = true; numberAfterE = false; } else if (c == '+' || c == '-') { if (i != start && (s[i - 1] != 'e' && s[i - 1] != 'E')) { return false; } } else { return false; } } return numberSeen && numberAfterE; } };
bool isNumber(const char *s) { string ss(s); trim(ss); bool numsign = 0; bool pointsign = 0; bool esign = 0; bool numafte = 0; int len = ss.size(); for(int i=0;i<len;++i){ if(ss[i]>='0'&&ss[i]<='9'){ numsign = 1; numafte = 1; }else if(ss[i] == '.'){ if(pointsign||esign)return false; pointsign = 1; }else if(ss[i]=='e'){ if(esign||!numsign)return false; esign = 1; numafte = 0; }else if(ss[i]=='+'||ss[i]=='-'){ if(i!=0&&ss[i-1]!='e')return false; } else return false; } return numsign&&numafte; } void trim(string &s){ if(!s.empty()){ s.erase(0,s.find_first_not_of(' ')); s.erase(s.find_last_not_of(' ')+1); } }
bool isNumber(const char *s) { // 需要考虑情况: // 非e的字母,是否有e,是否有小数点, // 是否为负数,e的指数是否为负数 string str(s); // 先将首尾的空格去掉 while (str.length() > 0 && str[0] == ' ') str = str.substr(1); while (str.length() > 0 && str[str.length() - 1] == ' ') str = str.substr(0, str.length() - 1); if (str.length() == 0) return false; bool hasE = false, isDecimal = false, isSign = false, isESign = false; for (int i = 0; i < str.length(); i ++) { char c = str[i]; if (c == '-' || c == '+') { // 当前数字没有正负号,后面必须为数字或'.' if (!isSign && i == 0 && i < str.length() - 1 && (str[i + 1] >= '0' && str[i + 1] <= '9') || str[i + 1] == '.') isSign = true; // 为e或E的符号,必须在e或E的后面,且e或E的后面没有过符号,且+/-不在字符串的最后一个 else if (hasE && i > 0 && (str[i - 1] == 'e' || str[i - 1] == 'E') && !isESign && i != str.length() - 1) isESign = true; else return false; } else if (c == '.') { // 没有过.,且没有过e或者E,'.'的前面或者后面需有数字 if (!hasE && !isDecimal && ((i != 0 && str[i - 1] >= '0' && str[i - 1] <= '9') || (i + 1 <= str.length() - 1 && str[i + 1] >= '0' && str[i + 1] <= '9'))) isDecimal = true; else return false; } else if (c == 'e' || c == 'E') { // 没有过e或者E,前面需要是数字或者'.' if (!hasE && i != 0 && ((str[i - 1] >= '0' && str[i - 1] <= '9') || str[i - 1] == '.') && i != str.length() - 1) hasE = true; else return false; } else if (c < '0' || c > '9') { return false; } } return true; }
//数字由三部分组成:整数部分,小数部分,指数部分 //注意数字里面含有空格 //数值的字符串遵循模式A[.[B]][e|EC]或者.B[e|EC] class Solution { private: int pos=0; public: bool isNumber(const char *s) { if(s==nullptr) return false; while(s[pos]==' ') pos++; //判断整数部分 bool numeric=scanInteger(s); //判断小数部分 if(s[pos]=='.'){ pos++; //小数可以没有整数部分:.123 //小数点后面可以没有数字:123. //小数点前面和后面可以都有数字:123.4 numeric=scanUnsignedInteger(s)||numeric;//注意||符号两边的顺序,必须保证scanUnsignedInteger(s)执行 } //判断指数部分 if(s[pos]=='e'||s[pos]=='E'){ pos++; //当e|E前面没有数字时,整个字符串不能表示数字:.e1 //当e|E后面没有整数时,整个字符串不能表示数字:12e、12e+5.4 numeric=numeric&&scanInteger(s); } //忽略掉三种情况后字符串后面的空格 while(s[pos]==' ') pos++; return numeric&&s[pos]=='\0';//保证三种情况后,字符串位于末尾 } bool scanUnsignedInteger(string s){ int temp=pos; while(s[pos]>='0'&&s[pos]<='9') pos++; return pos>temp;//如果pos>temp,表示含有数字 } bool scanInteger(string s){ if(s[pos]=='+'||s[pos]=='-') pos++; return scanUnsignedInteger(s); } };