《剑指Offer》-20.表示数值的字符串

题干

请实现一个函数用来判断字符串是否表示数值(包括整数和小数),例如,字符串 +1005e2-1233.1416-1E-16 都表示数值,但 12e1a3.141.2.3+-512e+5.4 都不是。

解题思路

数值字符串的模式 A[.[B]][e|EC],A是数值的整数部分,有正负值区分,B是数值的小数部分,紧跟着小数点,C为指数部分,紧跟着e或E,C也有正负值区分。

在小数里可能没有整数部分,整数后也可能只有小数点而没有小数部分。

因此可以按照字符串是否符合这个模式来判断是否是数值。

代码实现

function isNumeric($str)
{
    if (!isset($str)) {
        return false;
    }
    $idx = 0;
    $numeric = scanInteger($str, $idx);

    if ($str[$idx] == '.') {
        $idx++;

        /**
         * 小数可以没有整数部分,如.123 等于 0.123
         * 小数点后面可以没有数字,如123. 等于 123.0
         * 小数点前后都有数字
         */
        $numeric = scanUnsignedInteger($str, $idx) || $numeric;
    }
    if (isset($str[$idx]) && ($str[$idx] == 'e' || $str[$idx] == 'E')) {
        $idx++;
        /**
         * e|E 后面必须有数字,且必须是整数
         */
        $numeric = $numeric && scanInteger($str, $idx);
    }

    return $numeric && !isset($str[$idx]);
}

function scanInteger($str, &$idx)
{
    if ($str[$idx] == '+' || $str[$idx] == '-') {
        $idx++;
        return scanUnsignedInteger($str, $idx);
    }

    return scanUnsignedInteger($str, $idx);
}

function scanUnsignedInteger($str, &$idx)
{
    $hasNumeric = false;
    while (isset($str[$idx]) && $str[$idx] >= '0' && $str[$idx] <= '9') {
        $idx++;
        $hasNumeric = true;
    }

    return $hasNumeric;
}

var_dump(isNumeric('123.'));
var_dump(isNumeric('.123'));

你可能感兴趣的:(《剑指Offer》-20.表示数值的字符串)