Niuke.com's sword refers to Offer - a string representing a numerical value

Topic description

Please implement a function to determine whether a string represents a numeric value (including integers and decimals). For example, the strings "+100", "5e2", "-123", "3.1416" and "-1E-16" all represent numeric values. But neither "12e", "1a3.14", "1.2.3", "+-5" nor "12e+4.3".

method one:

Scan the input string str, if it encounters numbers 0~9, continue to scan the next one; if encounter special characters: +, -, decimal point '.', e, E, it will be detected according to the following standards; if If other characters are encountered, return false;

After encountering special characters, judge according to the following rules:

1. If it is + or -: the +- sign can only appear at the beginning of str or after the characters e and E, so judge if( i == 0 || str[i-1] == 'e' || str[ i-1] == 'E' ), if yes, continue to the next one, otherwise return false;

2. If it is a decimal point '.': if it does not meet the following rules, return false, otherwise continue to the next

  • Need to judge that the decimal point cannot be located at the end of str
  • No decimal point can appear after e and E
  • The decimal point cannot appear twice or more
  • Only numbers 0-9 or +, - are allowed before the decimal point
  • The number after the decimal point can only be 0~9 (not sure, the sword refers to the number after the decimal point written in the offer book, such as 233. It is equivalent to 233.0, which is legal, but it is also overwritten in the code)
3. If it is e, E : if it does not meet the following rules, return false, otherwise continue to the next
  • It is necessary to judge that e and E cannot be located at the beginning or end of str
  • e, E cannot appear twice or more
  • e, E can only be preceded by numbers 0~9
  • e, E can only be followed by numbers 0~9 or +, -

code

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' ) //If the number 0~9 is encountered, continue to scan the next one
                continue;
            else if( str[i] == '+' || str[i] == '-' )
            {
                if( i == 0 || str[i-1] == 'e' || str[i-1] == 'E' ) //+- sign can only appear at the beginning of str or at the characters e, E Later
                    continue;
                else
                    return false;
            }
            else if( str[i] == '.' )
            {
                if( flag_dot ) //The decimal point cannot appear twice or more
                    return false;
                flag_dot = true;
                if( str[i+1] == '\0' ) //The decimal point cannot be at the end of str
                    return false;
                if( flag_e ) //The decimal point cannot appear after e and E
                    return false;
                if( i != 0 && !(( str[i-1] >= '0' && str[i-1] <= '9' ) || str[i-1] == '+' || str [i-1] == '-' )) //The number before the decimal point can only be 0~9 or +, -
                    return false;
                if( !( str[i+1] >= '0' && str[i+1] <= '9' ) ) //The number after the decimal point can only be 0~9
                    return false;
            }
            else if( str[i] == 'e' || str[i] == 'E' )
            {
                if( flag_e ) // can't appear twice or more
                    return false;
                flag_e = true;
                if( i == 0 || str[i+1] == '\0' ) //e and E cannot be at the beginning or end of str
                    return false;
                if( !( str[i-1] >= '0' && str[i-1] <= '9' ) ) //e and E can only be numbers 0~9
                    return false;
                if( !(( str[i+1] >= '0' && str[i+1] <= '9' ) || str[i+1] == '+' || str[i+1] == '-') ) //e, E can only be followed by numbers 0~9 or +, -
                    return false;
            }
            else
                return false;
        }
         
        return true;
    }
 
};

Method 2: (from the second edition of Jianzhi offer)

Legal numbers can be represented as A[.[B]][e|EC] or .B[e|EC], where A is the integer part of the number, B followed by the decimal point is the fractional part of the number, and C followed Let e ​​and E be the exponential part of the value. In a decimal, there can be no integer part of the value, so the A part is not necessary. If a number does not have an A part, the decimal part cannot be empty.

Parts A and C above are both digit strings from 0 to 9 that may start with + and -; part B is also a digit string from 0 to 9, but cannot contain + and -.

When judging whether the string conforms to the above pattern, start scanning from the beginning, part A is optional, if it encounters a decimal point '.', start scanning part B. If e, E are encountered, start scanning part C.

code

class Solution {
public:
    bool isNumeric(const char* str)
    {
        if(str == nullptr)
            return false;

        bool numeric = scanInteger(&str);

        // If '.' appears, next is the fractional part of the number
        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);
    }
};

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325628418&siteId=291194637