有效数判定 Valid Number

来源:互联网 发布:怎样开淘宝网店卖衣服 编辑:程序博客网 时间:2024/05/18 03:58

问题:给出一个字符串,判断它是否是一个有效的数字。

什么叫有效的数字呢?

整数 ,小数 "2.5",正数 "+25",负数"-25",科学计数法"-2e1+0"。

特殊用例:

“.5”, “5.” 认为是有效数字。

无效用例:

“.", "e25", "25e", "2e5e5", "2.5.5", "2e2.5"

输入检查:左右两端出现空格是允许的,内部不能有空格。

方法1:依据上面所能想到的无效用例,处理零碎的细节。

方法2:将零碎的细节用有限状态自动机来表示。

方法3:偷懒直接用strtod函数。


方法1:处理零碎的细节。

class Solution {public:    bool isNumber(const char *s) {        if(s == NULL)            return false;                    int ex, dot;        ex = dot = 0; // only once                while(*s == ' ') // space            s++;                    if(*s == '+' || *s == '-') // sign            s++;                    if(isNum(*s)) // first char is numeric            s++;        else if(*s == '.') // if first char is '.'        {            s++;            dot = 1;            if(isNum(*s)) // then second char has to be numeric                s++;            else                return false;        }        else            return false;                while(*s != '\0')        {            if(*s == '.')            {                if(ex == 1 || dot == 1)                    return false;                dot = 1;            }            else if(*s == 'e')            {                if(ex == 1)                    return false;                ex = 1;                if(*(s+1) == '+' || *(s+1) == '-') //sign for exponent                    s++;                if(!isNum(*(s+1))) // numeric after 'e'                     return false;            }            else if(*s == ' ')  // space has to be on the right side            {                break;            }            else if(!isNum(*s)) //other letter            {                return false;            }                        s++;        }        while(*s == ' ') // space            s++;        if(*s == '\0')            return true;        else            return false;    }        bool isNum(const char c)    {        return (c >= '0' && c <= '9'); // 0<=c<=9    }};

方法2:有限状态自动机。

对于这个思想,最重要的是构建状态转换矩阵。其中,每一行代表一种状态,每一列代表使状态转移的一种输入。

可能的输入有6种:无效字符0、空格1、正负号2、数字3点4、e5。

可能的状态有8种:
-1 错误态,任何状态接收到无效字符都会进入错误态,一旦进入错误态,状态就不会再转换下去。
0  初始态,可接受空格、正负号、数字、点。
1  接收到正负号而来,可接受数字、点。
2  由状态3接收到点而来,可接受数字、空格、e。
3  由状态0/1/3接收到数字而来,可接受数字、e、空格、点。
4  由状态2/3/9接收到数字而来,可接受数字、e、空格。
5  由状态2/3/4接收到e而来,可接受正负号、数字。
6  由状态5接收到正负号而来,可接受数字。
7  由状态5/6接收到数字而来,可接受数字、空格。
8  由状态2/3/4/7接收到空格而来,可接受空格。
9  由状态0/1接收到点而来,可接受数字。

状态0是初始状态,状态2、3、4、7、8可作为终止状态。

根据状态和输入,构造状态转换矩阵。

{
     -1, 0, 1, 3, 9, -1, //状态0:""
     -1, -1,-1, 3, 9, -1, //状态1:"+"
     -1, 8, -1, 4, -1, 5, //状态2:"2."
     -1, 8, -1, 3, 2, 5, //状态3:"2"
     -1, 8, -1, 4, -1, 5, //状态4:"2.3"
     -1, -1, 6, 7, -1, -1, //状态5:"2.3e"
     -1, -1, -1, 7, -1, -1, //状态6:"2.3e+"
     -1, 8, -1, 7, -1, -1, //状态7:"2.3e+4"
     -1, 8, -1, -1, -1, -1, //状态8:"2.3e+4 "
     -1, -1, -1, 4, -1, -1 //状态9:"."
};

#include <iostream>#include <stdio.h>using namespace std;class Solution {public:    enum InputType    {        INVALID,    //0        SPACE,      //1        SIGN,       //2        DIGIT,      //3        DOT,        //4        EXPONENT,   //5    };       bool isNumber(const char *s) {        if(s == NULL)            return false;               const int transitionTable[][6] =        {            -1, 0,  1, 3, 9, -1,      //状态0:""            -1, -1,-1, 3, 9, -1,     //状态1:"+"            -1, 8, -1, 4, -1, 5,      //状态2:"2."            -1, 8, -1, 3, 2, 5,       //状态3:"2"            -1, 8, -1, 4, -1, 5,      //状态4:"2.3"            -1, -1, 6, 7, -1, -1,     //状态5:"2.3e"            -1, -1, -1, 7, -1, -1,    //状态6:"2.3e+"            -1, 8,  -1, 7, -1, -1,    //状态7:"2.3e+4"            -1, 8,  -1, -1, -1, -1,   //状态8:"2.3e+4 "            -1, -1, -1, 4, -1, -1     //状态9:"."        };        int state = 0;        InputType input;        while(*s != 0)        {            if(*s == ' ')                input = SPACE;            else if(*s == '+' || *s == '-')                input = SIGN;            else if(*s == '.')                input = DOT;            else if(*s == 'e' || *s == 'E')                input = EXPONENT;            else if(*s >= '0' && *s <= '9')                input = DIGIT;            else                input = INVALID;                       state = transitionTable[state][input];            if(state == -1)                return false;            ++s;            //cout<<state<<" ";        }        //cout<<endl;        return (state == 2 || state == 3 || state == 4 || state == 7 || state == 8);    }};int main(){    Solution s;    char str[100];    bool r;    while(scanf("%s", str) != EOF)    {        r = s.isNumber(str);        cout<<"result :"<<r<<endl;    }    return 1;}

方法3:偷懒。

double strtod (const char* str, char** endptr);

将字符串形式的浮点数转化为double类型。 
参数一,str为输入字符串。
参数二,二重指针,函数返回后,endptr会指向str中第一个浮点数之后的位置。
返回值,转化成的double浮点数。

class Solution {public:    bool isNumber(const char *s) {        char *left;        strtod(s, &left);        if(left == s)            return false;        while(*left != 0)        {            if(*left != ' ')                return false;            ++left;        }        return true;    }};

0 0
原创粉丝点击