这道题目有点类似于atoi(将字符串转化为整数),回想一下atoi:如果第一个非空格字符不存在或者不是数字也不是正负号则返回零,否则开始做类型转换,之后检测到非数字(包括结束符 \0) 字符时停止转换,返回整型数。

这道题目里面我们采取以下步骤:

  1. 忽略前置空格和后置空格
  2. 正负号只能出现在最前面
  3. 句点只能出现一次
  4. 不能含有正负号、句点、数字以外的字符
  5. 不能为空
  6. 不能是单独的正负号或句点

如果是科学计数法,需要符合:

  1. 没有空格紧邻e
  2. e的前面是数字
  3. e的后面是整数

具体的实现方案:

  • 先判断是否包含e
  • 如果包含e,则先判断e的前后是否紧邻空格
    • 如果是的,返回false
    • 如果不是,判断e的前面是否为数字,后面是否为整数
  • 如果不包含e,直接判断是否为数字
  • 为了实现方便,定义了一个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;
    }
};