请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。

思路:

分析这种字符串的规律,可以表示整数,小数及指数三类,分别可以表示为[+/-]number, [+/-]number[e/E][+/-]number, [+/-][number].number

  1. 首先扫描第一个字符,判断是否为正负符号;
  2. 设置number,decimal,hasE标志计算整数,小数点,e/E的数量;
  3. 尽可能的多扫描0-9的数位,若碰到小数点,则判断三个标志位是否符合标准,继续扫描下一位;
  4. 若碰到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);
    }

};