题目:请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串“+100”、“5e2”、“-123”、“3.1416”及“-1E-16”都表示数值,但“12e”、“1a3.14”、“1.2.3”、“+-5”以及“12e+5.4”都不是。
思路:
这道题很考验细节的处理和分析。首先要知道什么样的表示方法才是对的,才能够去进行判断。首先整数部分不是必要的,但是如果没有整数部分,那么小数部分就不能为空。还有小数点后面可以没有数字,小数点前面也可以没有数字。指数的前后都必须有整数才能正确地表示数字,这些情况都要考虑到。然后按照逐个字符进行比对,来判断这个字符串是否表示数值。
- 首先判断有没有整数部分,用numeric来记录true或者false;
- 再判断有没有小数点,以及小数点后面有没有数字;
- 再判断有没有指数,指数后面有没有整数。
代码:
bool scanUnsignedInteger(const char** str)
{
const char*before = *str;
while (**str!='\0'&&**str>'0'&&**str<='9')
{
++(*str);
}
//当str中存在若干0~9的数字时,返回true
return *str > before;
}
bool scanInteger(const char**str)
{
if (**str == '+' || **str == '-')
++(*str);
return scanUnsignedInteger(str);
}
bool isNumeric(const char*str)
{
if (str == nullptr)
return false;
bool numeric = scanInteger(&str);//&传入的是地址,这里不是引用的意思
//如果出现‘.',则接下来是数字的小数部分
if (*str == '.')
{
++str;
//下面一行代码用||的原因:
//1.小数可以没有整数部分,如.123等于0.123;
//2.小数点后面可以没有数字,如233.等于233.0
//3.小数点前后可以都有数字如233.666
numeric = scanInteger(&str) || numeric;
}
//如果出现‘e'或者'E',则接下来是数字的指数部分
if (*str == 'e' || *str == 'E')
{
++str;
//下面一行代码用&&的原因:
//1.当e或者E前面没有数字时,整个字符串不能表示数字,如.e1、e1;
//2.当e或者E后面没有整数时,整个字符串不能表示数字,如12e、12e+5.4;
numeric = numeric && scanInteger(&str);
}
return numeric && *str == '\0';
}
复习:
思路如上面说的,要注意的是检查数字的时候传入的是指针的引用,因为要改变指针指向的位置,如果传入的是指针,那么只是实参指针的复制,函数运行结束之后,不会改变原指针的指向位置。
二刷代码:
bool scanUnsignedInterger(const char** str)
{
const char* before = *str;
while (**str>='0'&&**str<='9'&&**str!='\0')
{
++(*str);
}
return *str > before;
}
bool scanSignedInteger(const char** str)
{
if (**str == '-' || **str == '+')
++(*str);
return scanUnsignedInterger(str);
}
bool isNumeric(const char*str)
{
if (str == nullptr)
return false;
bool isNumeric = scanSignedInteger(&str);
if (*str == '.')
{
++str;
isNumeric = isNumeric || scanUnsignedInterger(&str);
}
if (*str == 'e' || *str == 'E')
{
++str;
isNumeric = isNumeric && scanUnsignedInterger(&str);
}
return isNumeric && *str == '\0';
}