牛客网剑指Offer——表示数值的字符串

题目描述

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

方法一:

对输入的字符串str进行扫描,如果遇到数字0~9,则继续扫描下一个;如果遇到特殊字符:+,-,小数点'.',e,E,则按照下列标准进行检测;如果遇到其他字符,则返回false;

遇到特殊字符后,按照如下规则进行判断:

1、如果是+或者-:+-号只能出现在str开头或者在字符e、E之后,所以判断if( i == 0 || str[i-1] == 'e' || str[i-1] == 'E' ),是则继续下一个,否则返回false;

2、如果是小数点'.':不符合以下规则则返回false,否则继续下一个

  • 需要判断小数点不能位于str的末尾
  • 在e、E的后面不能出现小数点
  • 小数点不能出现两次或两次以上
  • 小数点前只能是数字0~9或者+、-
  • 小数点后只能是数字0~9(不确定,剑指offer书上写的小数点后可以没有数字,如233.相当于233.0,是合法的,但代码中这样写了也是过了的)
3、如果是e、E:不符合以下规则则返回false,否则继续下一个
  • 需要判断e、E不能位于str的的开头或者末尾
  • e、E不能出现两次或两次以上
  • e、E前只能是数字0~9
  • e、E后只能是数字0~9或者+、-

代码

class Solution {
public:
    bool isNumeric(char* str)
    {
        if( str == nullptr )
            return false;
        bool flag_e = false;
        bool flag_dot = false;
        for( int i=0;str[i]!='\0';i++ )
        {
            if( str[i] >= '0' && str[i] <= '9' ) //遇到数字0~9,则继续扫描下一个
                continue;
            else if( str[i] == '+' || str[i] == '-' )
            {
                if( i == 0 || str[i-1] == 'e' || str[i-1] == 'E' ) //+-号只能出现在str开头或者在字符e、E之后
                    continue;
                else
                    return false;
            }
            else if( str[i] == '.' )
            {
                if( flag_dot ) //小数点不能出现两次或两次以上
                    return false;
                flag_dot = true;
                if( str[i+1] == '\0' ) //小数点不能位于str的末尾
                    return false;
                if( flag_e ) //在e、E的后面不能出现小数点
                    return false;
                if( i != 0 && !(( str[i-1] >= '0' && str[i-1] <= '9' ) || str[i-1] == '+' || str[i-1] == '-' )) //小数点前只能是数字0~9或者+、-
                    return false;
                if( !( str[i+1] >= '0' && str[i+1] <= '9' ) ) //小数点后只能是数字0~9
                    return false;
            }
            else if( str[i] == 'e' || str[i] == 'E' )
            {
                if( flag_e ) //不能出现两次或两次以上
                    return false;
                flag_e = true;
                if( i == 0 || str[i+1] == '\0' ) //e、E不能位于str的的开头或者末尾
                    return false;
                if( !( str[i-1] >= '0' && str[i-1] <= '9' ) ) //e、E前只能是数字0~9
                    return false;
                if( !(( str[i+1] >= '0' && str[i+1] <= '9' ) || str[i+1] == '+' || str[i+1] == '-') ) //e、E后只能是数字0~9或者+、-
                    return false;
            }
            else
                return false;
        }
         
        return true;
    }
 
};

方法二:(出自剑指offer第二版)

合法的数值可以表示为A[.[B]][e|EC]或者.B[e|EC],其中A为数值的整数部分,B紧跟着小数点为数值的小数部分,而C紧跟着e、E为数值的指数部分。在小数中,可以没有数值的整数部分,所以A部分不是必须的,如果一个数没有A部分,则小数部分不能为空。

上述A和C部分都是可能以+、-开头的0~9的数位串;B部分也是0~9的数位串,但不能有+、-。

判断字符串是否符合上述模式时,从头开始扫描,A部分可有可无,如果遇到小数点'.'后,则开始扫描B部分。如果遇到e、E,则开始扫描C部分。

class Solution {
public:
    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 = scanUnsignedInteger(&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 scanUnsignedInteger(const char** str)
    {
        const char* before = *str;
        while(**str != '\0' && **str >= '0' && **str <= '9')
            ++(*str);

        // 当str中存在若干0-9的数字时,返回true
        return *str > before;
    }

    // 整数的格式可以用[+|-]B表示, 其中B为无符号整数
    bool scanInteger(const char** str)
    {
        if(**str == '+' || **str == '-')
            ++(*str);
        return scanUnsignedInteger(str);
    }
};

猜你喜欢

转载自blog.csdn.net/qq_36132127/article/details/80166727