题目描述
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。
数值(按顺序)可以分成以下几个部分:
- 若干空格
- 一个 小数 或者 整数
- (可选)一个
'e'
或'E'
,后面跟着一个 整数 - 若干空格
小数(按顺序)可以分成以下几个部分:
- (可选)一个符号字符(
'+'
或'-'
) - 述格式之一:
- 至少一位数字,后面跟着一个点
'.'
- 至少一位数字,后面跟着一个点
'.'
,后面再跟着至少一位数字 - 一个点
'.'
,后面跟着至少一位数
- 至少一位数字,后面跟着一个点
整数(按顺序)可以分成以下几个部分:
- (可选)一个符号字符(
'+'
或'-'
) - 至少一位数字
部分数值列举如下:
["+100", "5e2", "-123", "3.1416", "-1E-16", "0123"]
部分非数值列举如下:
["12e", "1a3.14", "1.2.3", "+-5", "12e+5.4"]
题目直达
力扣https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof/
解题思路
从题目描述中,我们可以知道,一个字符串如果是数值,它由:
若干空格、小数 /整数、e整数、若干空格
组成。
按题目定义的格式,对字符串直接分段判断更直观。
主要算法流程为:
- 去掉头尾空格,处理剩下部分。
- 判断是否带e/E
- 带,要求是整数或小数
- 带,以e/E为分隔符,分为前后两部分,前面要求整数或小数,后面要求整数
C++代码实现
根据代码注释和上面的算法流程 ,很好理解。
// 判断是不是符号位,函数体少,建议使用内联函数。
static inline bool isSignChar(char c)
{
return c == '+' || c == '-';
}
//判断是不是数字
static inline bool isNumChar(char c)
{
return c >= '0' && c <= '9';
}
// 判断是否整数
static bool isInteger(const char* s, int len)
{
//例如:+10,3
if (len <= 0)
return false;
// 判断符号字符
if (isSignChar(s[0]) && len > 1)
{
++s;
--len;
} // 10,2
for (int i = 0; i < len; ++i)
{
if (!isNumChar(s[i])) //如果不是数字
return false;
}
return true;
}
// 判断是否小数
static bool isDecimal(const char* s, int len)
{
// 例如 +15.5,+10.,+.5
if (len <= 0)
return false;
if (isSignChar(s[0]) && len > 1)
{
++s;
--len;
}
int dot_index = -1;
for (int i = 0; i < len; ++i)
{
if (s[i] == '.')
{
if (dot_index == -1)
dot_index = i;
else //只能有一个.
return false;
}
else if (!isNumChar(s[i])) //符号位之后,既不是. 也不是数字
return false;
}
// 至少存在 '.' 和一个数字
return dot_index >= 0 ? len > 1 : false;
}
class Solution
{
public:
bool isNumber(string s)
{
const char* p = s.c_str();//string转char*
int len = s.length();
// 跳过头尾空格
const char* l = p, *r = p + len - 1;
while (l <= r && *l == ' ') ++l;
while (l <= r && *r == ' ') --r;
// 全是空格或空字符串
if (l > r)
{
return false;
}
// 搜索 e/E
const char* c = l;
while (c <= r && *c != 'e' && *c != 'E')
++c;
if (c < r) //这里 c必须小于r,因为如果有e,e后面必须是整数,c所处的位置代表的元素是e,c不能>=r了。
{
// 有 e/E,后面跟整数
return (isInteger(l, c - l) || isDecimal(l, c - l)) && isInteger(c + 1, r - c);
}
else // c>=r了。
{
// 无 e/E。判断整个字符串是整数还是小数。
return isInteger(l, r - l + 1) || isDecimal(l, r - l + 1);
}
}
};