请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。
思路:
分析这种字符串的规律,可以表示整数,小数及指数三类,分别可以表示为[+/-]number, [+/-]number[e/E][+/-]number, [+/-][number].number
- 首先扫描第一个字符,判断是否为正负符号;
- 设置number,decimal,hasE标志计算整数,小数点,e/E的数量;
- 尽可能的多扫描0-9的数位,若碰到小数点,则判断三个标志位是否符合标准,继续扫描下一位;
- 若碰到e/E,则判断三个标志位是否符合标准,且e/E下一位能为‘+/-’,继续扫描判断。
代码:bool isNumeric(char* string) { if (string == nullptr) return false; //一开始判断正负号是否存在 if (*string == '+' || *string == '-') string += 1; if (*string == '\0') return false; //计算整数,小数,E的数量 int number=0, decimal = 0, hasE = 0; //循环判断是否符合规则 while (*string!='\0') { //若当前字符为数字,标记整数为1 if (*string >= '0' && *string <= '9') { string++; number = 1; } //有小数点:若小数点数量超过1个或者在有一个小数点之前有过E,则返回false else if (*string == '.') { decimal += 1; string++; if (decimal > 1 || hasE > 0||*string=='\0') return false; } //有e或E:若小数点数量大于1或者e数量大于1或者E前面无整数,返回false else if (*string == 'e' || *string == 'E') { hasE += 1; string++; if (decimal > 1 || hasE > 1 || number < 1) return false; //E后面可跟着正负号 if (*string == '+' || *string == '-') { string++; } if (*string == '\0') return false; } //不满足以上几种情况,说明有其他超出规则之外的组合 else return false; } //顺利通过while循环,返回True; return true; }
FRESH...
class Solution { public: /* * 分三步: * 1.先尽可能扫描整数部分,可能前面有正负号,结果为A; * 2.若碰到小数点,就接着扫描后面的无符号整数部分,结果为B; * 若C=A||B为真,则小数就成立了。为什么是||呢? * 因为若A或B为真,小数就成立;如.123中A为false,B为true;如123.中A为true,B为false; * 3.若碰到e/E,就接诊扫描后面的无符号整数部分,结果为D; * 若C&&D为真,则指数就成立了。为什么是&&呢? * 因为指数需要前后都有数,反证一下:若C不成立,前面不是小数也不是整数,如+E9; * 若D不成立,后面不是无符号整数,如12e8.67就不行。所以必须C,D都为真。 */ bool isNumeric(const char* string) { if (string == nullptr) return false; //返回前半部分带符号整数结束的地方,即A的下一位 int integral = isIntegral(string, 0); //若返回值大于0,表示已经扫描完了A部分的整数,返回true;否则,表示前面没有整数,返回false; bool A = integral > 0; int decimal=integral; bool numerical=A; //接着看是否为小数部分 if (string[integral] == '.') { ++integral; decimal = isUnsignedIntegral(string, integral); //若返回值大于integral,表示已经扫描完了B部分的整数,返回true;否则,B部分没有整数,返回false; bool B = decimal > integral; //用numerical保存前面小数部分的扫描结果 numerical = A || B; } int exponent=decimal; //接着看是否为指数部分 if (string[decimal] == 'e' || string[decimal] == 'E') { ++decimal; //正常指数后边是带符号整数 exponent = isIntegral(string, decimal); bool C = exponent > decimal; numerical = C && numerical; } return numerical && string[exponent] == '\0'; } //从begin下标位置判断是否为无符号整数,并返回整数结束的地方 int isUnsignedIntegral(const char* string,int begin) { int i = begin; while (string[i]!='\0'&&isdigit(string[i])) { ++i; } return i; } //从begin下标位置判断是否为有符号整数,并返回整数结束的地方 int isIntegral(const char* string, int begin) { int i = begin; if (string[i] == '+' || string[i] == '-') ++i; //判断了正负号之后,就可以将程序交给判断无符号数代码了 return isUnsignedIntegral(string, i); } };