问题说明:
实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如:“+100”,“5e2”,“-123”,“-1e-16”,“2.345E9”都可表示数字,"12e","1a3.14","1.2.3","12e+5.4" 都不能表示数字。
分析:
可将表示数字的字符串抽象为:A [[.B]] [E|eC] 或者 .[B][E|eC]
其中:A,C 都是可能以 ‘+’或者 '-' 开头的0~9的数位串
B 也是0~9的数位串,但是前不能有 ‘+’或者 '-'
代码思路:
判断是否满足上述模式时,首先尽可能多的扫描0~9的数位即达到 A 部分,遇到“.”则开始扫描 B 部分,遇到“E”或者“e”则开始扫描 C 部分。
代码实现:
bool scanUnsignedInteger(const char **str)
{
const char* before = *str;
while (**str != '\0' && **str >= '0' && **str <= '9')
++(*str);
//当str中存在若干0~9的数字时,返回true
return *str > before; //*str > before表示区间有若干数
}
bool scanInteger(const char **str)
{
if (**str == '+' || **str == '-')
++(*str);
return scanUnsignedInteger(str);
}
bool isNumeric(const char *str)
{
if (str == NULL)
return false;
bool numeric = scanInteger(&str); //要修改指针的指向,传二级指针
if (*str == '.')
{
++str; //跳过 .
//代码用 || 的原因:
//1. 小数点可以没有整数部分,如 .123等于0.123
//2. 小数点后面没有数字,如 233. 等于 233.0
//3. 当然小数点前后都可以有数字,如 1.2
numeric = scanUnsignedInteger(&str) || numeric;
}
if (*str == 'e' || *str == 'E')
{
++str; //跳过e|E
//用&&的原因:
//当e之前无数字时,整个字符串不能表示数字,例如: E-1,e9 都不可以
//当e后面无数字时,整个字符串不能表示数字,例如:12E,1e 都不可以
numeric = numeric && scanInteger(&str);
}
return numeric && *str == '\0'; //当字符串到尾,且前面为真则真;即使前面为真后面不在字符串结尾就证明不是数字(例子: +1.2E-3PP)
}